Author Topic: BITRECORD & DCB  (Read 381 times)

jj2007

  • Member
  • *****
  • Posts: 7752
  • Assembler is fun ;-)
    • MasmBasic
BITRECORD & DCB
« on: June 03, 2017, 09:36:57 PM »
Testing how the DCB structure translates to assembler. This snippet compiles fine with M$ C compiler:
Code: [Select]
#include <windows.h>
#include <conio.h>

int main(int argc, char* argv[]) {
  DCB dcb={sizeof(DCB), 0x12345678, 0, FALSE, RTS_CONTROL_HANDSHAKE,FALSE,FALSE, FALSE,FALSE,FALSE,FALSE,DTR_CONTROL_HANDSHAKE,TRUE,TRUE,NULL,TRUE};
  // _asm int 3;
  _asm lea eax, dcb; //1c 00 00 00, 78 56 34 12, 00 98 00 00
  _asm lea edx, dcb.BaudRate;
  _asm lea ecx, dcb.BaudRate[4];
  _asm mov eax, [ecx];
  dcb.fBinary=1;
  // 00DC7E4A        ³.  8B45 E8                      mov eax, [ebp-18]
  // 00DC7E4D        ³.  83E0 CF                      and eax, FFFFFFCF
  // 00DC7E50        ³.  83C8 20                      or eax, 00000020
  // 00DC7E53        ³.  8945 E8                      mov [ebp-18], eax
  printf("ok");
  _getch(); // for use with console
}

sizeof(DCB) is 1Ch, 28 bytes, of which the BITRECORD is only 4 bytes, of course.
The 0x12345678 is the baudrate, nonsense obviously but it helps to find its location in Olly's memory dump.

So 00 98 00 00 -> 9800h is the expected result for the values discussed in Serial I/O communications (terminal) code

WinBase.h:
Code: [Select]
typedef struct _DCB {
    DWORD DCBlength;      /* sizeof(DCB)                     */
    DWORD BaudRate;       /* Baudrate at which running       */
    DWORD fBinary: 1;     /* Binary Mode (skip EOF check)    */
    DWORD fParity: 1;     /* Enable parity checking          */
    DWORD fOutxCtsFlow:1; /* CTS handshaking on output       */
    DWORD fOutxDsrFlow:1; /* DSR handshaking on output       */
    DWORD fDtrControl:2;  /* DTR Flow control                */
    DWORD fDsrSensitivity:1; /* DSR Sensitivity              */
    DWORD fTXContinueOnXoff: 1; /* Continue TX when Xoff sent */
    DWORD fOutX: 1;       /* Enable output X-ON/X-OFF        */
    DWORD fInX: 1;        /* Enable input X-ON/X-OFF         */
    DWORD fErrorChar: 1;  /* Enable Err Replacement          */
    DWORD fNull: 1;       /* Enable Null stripping           */
    DWORD fRtsControl:2;  /* Rts Flow control                */
    DWORD fAbortOnError:1; /* Abort all reads and writes on Error */
    DWORD fDummy2:17;     /* Reserved                        */
    WORD wReserved;       /* Not currently used              */
    WORD XonLim;          /* Transmit X-ON threshold         */
    WORD XoffLim;         /* Transmit X-OFF threshold        */
    BYTE ByteSize;        /* Number of bits/byte, 4-8        */
    BYTE Parity;          /* 0-4=None,Odd,Even,Mark,Space    */
    BYTE StopBits;        /* 0,1,2 = 1, 1.5, 2               */
    char XonChar;         /* Tx and Rx X-ON character        */
    char XoffChar;        /* Tx and Rx X-OFF character       */
    char ErrorChar;       /* Error replacement char          */
    char EofChar;         /* End of Input character          */
    char EvtChar;         /* Received Event character        */
    WORD wReserved1;      /* Fill for now.                   */
} DCB, *LPDCB;

P.S.: If you need a simple C replacement for Print Bin$(eax), see Is there a printf converter to print in binary format? ;)

TWell

  • Member
  • ****
  • Posts: 748
Re: BITRECORD & DCB
« Reply #1 on: June 04, 2017, 12:08:39 AM »
Another test
Code: [Select]
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <conio.h>

//DCB dcb={sizeof(DCB), 0x12345678, 0, FALSE, RTS_CONTROL_HANDSHAKE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,DTR_CONTROL_HANDSHAKE,TRUE,TRUE,NULL,TRUE};
DCB dcb={sizeof(DCB), 0x12345678, TRUE,FALSE,TRUE,TRUE,DTR_CONTROL_HANDSHAKE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,RTS_CONTROL_HANDSHAKE,FALSE,0};

int main(void)
{
char abits[33];
DWORD bm;
dcb.fBinary = 1;
bm = *((DWORD*)&dcb+2); // read 3. DWORD where the fBinary is
abits[32] = 0;
for (int i = 0; i < 32; i++)
abits[31 - i] = (bm & 1 << i)?'1':'0';
printf("%04Xh %s\n", bm, abits);
printf("ok");
_getch(); // for use with console
return 0;
}
Code: [Select]
202Dh 00000000000000000010000000101101
ok

jj2007

  • Member
  • *****
  • Posts: 7752
  • Assembler is fun ;-)
    • MasmBasic
Re: BITRECORD & DCB
« Reply #2 on: June 04, 2017, 01:48:19 AM »
Thanks, Tim - your test showed me the way to go :t
Code: [Select]
include \masm32\include\masm32rt.inc
include BitRecord.mac

.code
start:
  print "00000000000000000010000000101101", 9, "expected, see Tim's code", crlf
  print bin$(_Record(TRUE,FALSE,TRUE,TRUE,DTR_CONTROL_HANDSHAKE:2,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,RTS_CONTROL_HANDSHAKE:2,FALSE,0)), crlf
  inkey bin$(_RecordRev(0,FALSE,RTS_CONTROL_HANDSHAKE:2,FALSE,FALSE, FALSE,FALSE,FALSE,FALSE,DTR_CONTROL_HANDSHAKE:2,TRUE,TRUE,NULL,TRUE)), crlf
  exit
end start

Output:
Code: [Select]
00000000000000000010000000101101        expected, see Tim's code
00000000000000000010000000101101
00000000000000000010000000101101

_Record() uses the same order as the DBC structure, so we might declare that the "natural" order ;-)

There is no data or RECORD to be declared; the macro simply builds a single integer value. All elements represent one bit, except if they have e.g. DTR_CONTROL_HANDSHAKE:2, where :n represents the field's bit length.

Behaviour is the same for all assemblers (ML, UAsm, JWasm, AsmC).

jimg

  • Member
  • **
  • Posts: 196
Re: BITRECORD & DCB
« Reply #3 on: June 04, 2017, 04:02:08 AM »
Okay, I put together a prog for testing, and it seem to confirm everything I've been saying.

edit: replace zip.  minor cleanup not affecting results.
« Last Edit: June 04, 2017, 10:42:14 AM by jimg »