The MASM Forum

Miscellaneous => 16 bit DOS Programming => Topic started by: jj2007 on September 05, 2013, 04:04:55 AM

Title: Reg16 or reg32??
Post by: jj2007 on September 05, 2013, 04:04:55 AM
Hi Masm32 crew,

Just opened the Forum, and the four most recent posts are about exciting issues such as
- forest fires
- somebody requesting permission to scare people with CIA badges
- a Cafeteria fight and
- the Late Mr. Frost.

So I hope I won't offend anybody if I open a new thread about, you guessed it, assembler coding:

Val MACRO pStr
  push si
  mov si, pStr
  xor edx, edx
  xor eax, eax
  .While 1
   lodsb
   cmp al, "0"
   .Break .if Sign?
   lea edx, [4*edx+edx]
   lea edx, [2*edx+eax-"0"]
  .Endw
  pop si
  xchg eax, edx
  EXITM <eax>
ENDM


So far, so simple - it works:
  Print Str$(Val(Chr$("12345"))), " is 12345", 13, 10

The question is: Should such macros be limited to 16-bit registers, or is "mixed size" DOS code acceptable? Where would it cause problems?
Title: Re: Reg16 or reg32??
Post by: Gunther on September 05, 2013, 04:24:13 AM
Jochen,

Quote from: jj2007 on September 05, 2013, 04:04:55 AM
The question is: Should such macros be limited to 16-bit registers, or is "mixed size" DOS code acceptable? Where would it cause problems?

I think mixed size is acceptable. The only point is, we've to ensure that at least an 80386 processor is available.

Gunther
Title: Re: Reg16 or reg32??
Post by: jj2007 on September 05, 2013, 04:36:41 AM
Quote from: Gunther on September 05, 2013, 04:24:13 AMwe've to ensure that at least an 80386 processor is available

So it's a hardware, not a software issue? Mixed size would work in DOSBOX and/or "true" DOS?
Title: Re: Reg16 or reg32??
Post by: nidud on September 05, 2013, 05:48:39 AM
deleted
Title: Re: Reg16 or reg32??
Post by: FORTRANS on September 05, 2013, 06:18:07 AM
Hi,

   I would say it is mostly a hardware issue.  If it works, why not
use it?  I don't use 32-bit instructions very often.  But they sure
are useful when you need them.

   There may be issues of addressing limits when using 32-bit
registers in real mode.  And probably some other things, like
confusing myself with differing behavior between 32-bit and
16-bit instructions.

Regards,

Steve N.
Title: Re: Reg16 or reg32??
Post by: jj2007 on September 05, 2013, 06:21:12 AM
Quote from: nidud on September 05, 2013, 05:48:39 AM
pure x86 programs are very rare

But even a pure x86 program could handle a mov eax, ecx, provided .386 is specified, and the hardware allows it, right?

By the way, debug has serious problems to disassemble mixed size code. For example,
      pushd 10
      pop ecx
produces garbage in the disassembly (the code works fine).
Title: Re: Reg16 or reg32??
Post by: nidud on September 05, 2013, 07:02:26 AM
deleted
Title: Re: Reg16 or reg32??
Post by: nidud on September 05, 2013, 07:30:29 AM
deleted
Title: Re: Reg16 or reg32??
Post by: jj2007 on September 05, 2013, 07:36:36 AM
Quote from: nidud on September 05, 2013, 07:02:26 AMWell, it wouldn't be a pure .8086 program then since this CPU don't have extended registers like EAX

That makes sense, thanks.

Quote from: FORTRANS on September 05, 2013, 06:18:07 AMI don't use 32-bit instructions very often.  But they sure are useful when you need them

Indeed. I was playing with the ascii-to-word/word-to-ascii pair when I realised DWORD would be even better ;-)

include DosBasic.inc  ; attached
  Init
  mov eax, Val32(Chr$("-123456789"))
  Print Str$(eax), " is -123456789", 13, 10
  Print Str$(Val32(Chr$("-123456789"))), " is -123456789", 13, 10
  Print Str$(Val(Chr$("12345"))), " is 12345", 13, 10
  Print Str$(Val32(Chr$("123456789"))), " is 123456789", 13, 10
  Print Str$(-123456789), " is -123456789", 13, 10
  Inkey "bye"
  Exit 123
end start

This works fine. In contrast, the attached Fibonacci example has a 16-bit limit in the upper half.
Title: Re: Reg16 or reg32??
Post by: Antariy on September 05, 2013, 10:11:18 AM
Quote from: jj2007 on September 05, 2013, 04:04:55 AM
Just opened the Forum, and the four most recent posts are about exciting issues such as

:greensml:


Quote from: jj2007 on September 05, 2013, 04:04:55 AM
The question is: Should such macros be limited to 16-bit registers, or is "mixed size" DOS code acceptable? Where would it cause problems?

Yes, it will work. Generally speaking, 32 bit instructions differ from 16 bit instructions in the 16 bit code with prefix 66h added before the opcode. For 32 bit code it all is vice versa - 66h prefix will tell CPU that this instruction is 16 bit, so, for an instance, the data field for the MOV or PUSH etc is "shortened" (16 bit).
Byte sequences:

16 bit code:

68 34 12 (push (word) 1234)

66 68 78 56 34 12 (push (dword) 12345678)

6A 7F (push (word) 007F)

66 6A 7F (push (dword) 0000007F)

50 (push ax)

66 50 (push eax)


32 bit code:

68 78 56 34 12 (push (dword) 12345678)

66 68 34 12 (push (word) 1234 = pushw 1234)

6A 7F (push (dword) 0000007F)

66 6A 7F (push (word) 007F = pushw 7F)

50 (push eax)

66 50 (push ax)



Quote from: jj2007 on September 05, 2013, 06:21:12 AM
By the way, debug has serious problems to disassemble mixed size code. For example,
      pushd 10
      pop ecx
produces garbage in the disassembly (the code works fine).

DEBUG is aware only about 8086 instruction set. PUSH IMM is 80186 instuction.

BTW, in a DEBUG you can still use 32 bit code, but it is uncomfortable:

-a
1D25:0100 db 66
1D25:0101 mov ax,5678
1D25:0104 dw 1234
1D25:0106 db 66
1D25:0107 push ax
1D25:0108
-r
AX=0000  BX=0000  CX=0000  DX=0000  SP=FFEE  BP=0000  SI=0000  DI=0000
DS=1D25  ES=1D25  SS=1D25  CS=1D25  IP=0100   NV UP EI PL NZ NA PO NC
1D25:0100 66            DB      66
-d ffee
1D25:FFE0                                            00 00                 ..
1D25:FFF0  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
-t

AX=5678  BX=0000  CX=0000  DX=0000  SP=FFEE  BP=0000  SI=0000  DI=0000
DS=1D25  ES=1D25  SS=1D25  CS=1D25  IP=0106   NV UP EI PL NZ NA PO NC
1D25:0106 66            DB      66
-t

AX=5678  BX=0000  CX=0000  DX=0000  SP=FFEA  BP=0000  SI=0000  DI=0000
DS=1D25  ES=1D25  SS=1D25  CS=1D25  IP=0108   NV UP EI PL NZ NA PO NC
1D25:0108 7DCC          JGE     00D6
-d ffea
1D25:FFE0                                78 56 34 12 00 00             xV4...
1D25:FFF0  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
-
Title: Re: Reg16 or reg32??
Post by: sinsi on September 05, 2013, 12:15:56 PM
I'm pretty sure you can even use "mov eax,[edx+eax*2]", as long as the effective address doesn't pass 64K.
Title: Re: Reg16 or reg32??
Post by: Antariy on September 05, 2013, 12:59:36 PM
Quote from: sinsi on September 05, 2013, 12:15:56 PM
I'm pretty sure you can even use "mov eax,[edx+eax*2]", as long as the effective address doesn't pass 64K.

Yes, you're right :t But then the opcode needs one more prefix - 67h
Title: Re: Reg16 or reg32??
Post by: MichaelW on September 05, 2013, 01:11:55 PM
Quote from: Antariy on September 05, 2013, 10:11:18 AM
DEBUG is aware only about 8086 instruction set.

Which DEBUG?

http://www.japheth.de/debxxf.html


Title: Re: Reg16 or reg32??
Post by: japheth on September 05, 2013, 03:54:04 PM
Quote from: MichaelW on September 05, 2013, 01:11:55 PM
Which DEBUG?

http://www.japheth.de/debxxf.html

There's an even more sophisticated version of DEBUG available: https://sites.google.com/site/pcdosretro/enhdebug (https://sites.google.com/site/pcdosretro/enhdebug)
Title: Re: Reg16 or reg32??
Post by: jj2007 on September 05, 2013, 05:47:07 PM
Quote from: japheth on September 05, 2013, 03:54:04 PM
There's an even more sophisticated version of DEBUG available: https://sites.google.com/site/pcdosretro/enhdebug (https://sites.google.com/site/pcdosretro/enhdebug)

Better than the built-in version but

  pushd 10
  pop ecx


still gets disassembled as

66      DB      66
6A0A    PUSH    +0A
6659    POP     ECX


i.e. the size override prefix is not recognised as such.

Sinsi's code gets disassembled correctly, though:
67668B0442        MOV     EAX,[EDX][EAX*2]
Title: Re: Reg16 or reg32??
Post by: Antariy on September 05, 2013, 07:46:08 PM
Quote from: MichaelW on September 05, 2013, 01:11:55 PM
Quote from: Antariy on September 05, 2013, 10:11:18 AM
DEBUG is aware only about 8086 instruction set.

Which DEBUG?

http://www.japheth.de/debxxf.html

No, I meant the "standard" DEBUG coming with DOS/Windows
Title: Re: Reg16 or reg32??
Post by: Antariy on September 05, 2013, 08:25:31 PM
Contrary example: many disassemblers will "flawlessly" disassembly next piece, but without opcodes field you will not find why original program crashed

include \masm32\include\masm32rt.inc

.code
option prologue:none
option epilogue:none

printit proc    dwVal
    invoke crt_printf,CTXT("printit: %p",13,10),dword ptr [esp+4]
    db 66h
    ret 4
printit endp

start:

invoke printit,12345678h
invoke crt_printf,CTXT("RET LOL")

end start
Title: Re: Reg16 or reg32??
Post by: jj2007 on September 05, 2013, 09:08:54 PM
Olly gives you a comment at least...

00401012       À.  66:C2 0400          retn 4                                 ; 16-bit return
Title: Re: Reg16 or reg32??
Post by: Antariy on September 06, 2013, 12:00:52 AM
Quote from: jj2007 on September 05, 2013, 09:08:54 PM
Olly gives you a comment at least...

00401012       À.  66:C2 0400          retn 4                                 ; 16-bit return


Yes, I know. But statical disassembly analysis will not show it... if the disassembler doesn't track such things like Olly does or it doesn't show opcodes field. Though, all disassemblers do this, so, this is just a "fun" example :biggrin:
The interesting point is this kind of return works with IP and not with EIP - even though there's no "directly accessed" instruction pointer regester. The same it will do in 16 bit mode - work with EIP instead of IP.
Title: Re: Reg16 or reg32??
Post by: Gunther on September 06, 2013, 02:42:42 AM
Alex,

Quote from: Antariy on September 06, 2013, 12:00:52 AM
The interesting point is this kind of return works with IP and not with EIP - even though there's no "directly accessed" instruction pointer regester. The same it will do in 16 bit mode - work with EIP instead of IP.

This is a matter of course; we're speaking about DOS (Real Mode or V86 Mode). The things are different for 32 bit DPMI clients. But that's another story.

Gunther
Title: Re: Reg16 or reg32??
Post by: Antariy on September 06, 2013, 01:00:39 PM
Quote from: Gunther on September 06, 2013, 02:42:42 AM
Alex,

Quote from: Antariy on September 06, 2013, 12:00:52 AM
The interesting point is this kind of return works with IP and not with EIP - even though there's no "directly accessed" instruction pointer regester. The same it will do in 16 bit mode - work with EIP instead of IP.

This is a matter of course; we're speaking about DOS (Real Mode or V86 Mode). The things are different for 32 bit DPMI clients. But that's another story.

Gunther

Yes, tryings to set EIP in not-DPMI mode are fault.
Title: Re: Reg16 or reg32??
Post by: Gunther on September 07, 2013, 12:30:41 AM
Hi Alex,

Quote from: Antariy on September 06, 2013, 01:00:39 PM
Yes, tryings to set EIP in not-DPMI mode are fault.

it's not only for DPMI clients. If the basis of Protected Mode is VCPI, XMS or RAW, we would have the same effects. It's simply a question of the segment size: 16 bit segments need IP while 32-bit segments need EIP.

Gunther
Title: Re: Reg16 or reg32??
Post by: japheth on September 07, 2013, 05:02:17 PM
I'm a nitpicker, so I'll have to slightly correct some of the previous statements  :icon_mrgreen:

You can use 32-bit CALLs and RETs in 16-bit code segments and the opposite, using 16-bit CALLs and RETs in 32-bit, is also possible.

Here's a sample of a 16-bit code, calling a procedure with 32-bit call/ret:


.286
.model small
.dosseg
.stack 400h
.386

.code

msg1 db "abc$"

p1:
mov ah,9
mov dx,offset msg1
int 21h
;; retd    ;!!!
        db 66h
        ret

start:
push cs
pop ds
call near32 ptr p1    ;!!!
mov ah,4ch
int 21h

end start


And a 32-bit DPMI sample, using 16-bit call/ret:


;--- DPMICL32.ASM: 32bit DPMI application written in MASM syntax.
;--- assemble: JWasm -mz dpmicl32.asm

LF  equ 10
CR  equ 13

    .386
    .model small

    .dosseg     ;this ensures that stack segment is last

    .stack 1024

    .data

szWelcome db "welcome in protected-mode",CR,LF,0

    .code

start:
    mov esi, offset szWelcome
    call near16 ptr printstring         ;!!!
    mov ax, 4C00h   ;normal client exit
    int 21h

;--- print a string in protected-mode with simple
;--- DOS commands not using pointers.

printstring:
    lodsb
    and al,al
    jz stringdone
    mov dl,al
    mov ah,2
    int 21h
    jmp printstring
stringdone:
;;    retw    ;!!!
    db 66h
    ret

;--- now comes the 16bit initialization part

_TEXT16 segment use16 word public 'CODE'

start16:
    mov ax,ss
    mov cx,es
    sub ax, cx
    mov bx, sp
    shr bx, 4
    inc bx
    add bx, ax
    mov ah, 4Ah     ;free unused memory
    int 21h

    mov ax, 1687h   ;DPMI host installed?
    int 2Fh
    and ax, ax
    jnz nohost
    push es         ;save DPMI entry address
    push di
    and si, si      ;requires host client-specific DOS memory?
    jz nomemneeded
    mov bx, si
    mov ah, 48h     ;alloc DOS memory
    int 21h
    jc nomem
    mov es, ax
nomemneeded:
    mov ax, DGROUP
    mov ds, ax
    mov bp, sp
    mov ax, 0001        ;start a 32-bit client
    call far ptr [bp]   ;initial switch to protected-mode
    jc initfailed

;--- now in protected-mode

;--- create a 32bit code selector and jump to 32bit code

    mov cx,1
    mov ax,0
    int 31h
    mov bx,ax
    mov cx,_TEXT
    mov dx,cx
    shl dx,4
    shr cx,12
    mov ax,7
    int 31h     ;set base address
    mov dx,-1
    mov cx,0
    mov ax,8
    int 31h     ;set descriptor limit to 64 kB
    mov cx,cs
    lar cx,cx
    shr cx,8
    or ch,40h
    mov ax,9
    int 31h     ;set code descriptors attributes to 32bit
    push ebx
    push offset start
    retd        ;jump to 32-bit code

nohost:
    mov dx, offset dErr1
    jmp error
nomem:
    mov dx, offset dErr2
    jmp error
initfailed:
    mov dx, offset dErr3
error:
    push cs
    pop ds
    mov ah, 9
    int 21h
    mov ax, 4C00h
    int 21h

dErr1 db "no DPMI host installed",CR,LF,'$'
dErr2 db "not enough DOS memory for initialisation",CR,LF,'$'
dErr3 db "DPMI initialisation failed",CR,LF,'$'

_TEXT16 ends

    end start16


See the near16 and near32 overrides for the call instructions; also retw and retd are used here, to avoid using the ugly DB directive to add size prefixes. This syntax is supported by masm and jwasm.

But the limitations for 16-bit are still true, of course: the value of EIP must remain < 0x10000.

EDIT: RETW/RETD apparently always create a FAR return, so you'll have to use DB instead.
Title: Re: Reg16 or reg32??
Post by: Gunther on September 07, 2013, 07:55:47 PM
Andreas,

Quote from: japheth on September 07, 2013, 05:02:17 PM
I'm a nitpicker, so I'll have to slightly correct some of the previous statements  :icon_mrgreen:

You can use 32-bit CALLs and RETs in 16-bit code segments and the opposite, using 16-bit CALLs and RETs in 32-bit, is also possible.

sure, no question. But don't forget the 66h prefix byte. That was my point.

Gunther
Title: Re: Reg16 or reg32??
Post by: Antariy on September 07, 2013, 08:05:10 PM
Quote from: japheth on September 07, 2013, 05:02:17 PM
Here's a sample of a 16-bit code, calling a procedure with 32-bit call/ret:

Far call and return will work, too, while CS and EIP value are both DWORDs values in the stack, and EIP is in 16 bit range.

16 bit call/ret in 32 bit mode is possible when the "guard area" <10000h is commited and is executable (since the CALL/RET itself doesn't change anything with the segmentation (until it's not FAR) - 16 bit CALL/RET in 32 bit code still remain the code 32 bit, the point of my #16 post was that operand size override prefix "plays" with (E)IP size, not the modes (16/32 bit), so, in "usual program" 16 bit return in the program will cause a crash, since the area of return is not commited)

Quote from: japheth on September 07, 2013, 05:02:17 PM
But the limitations for 16-bit are still true, of course: the value of EIP must remain < 0x10000.

That's what I meant here

Quote from: Antariy on September 06, 2013, 01:00:39 PM
Yes, tryings to set EIP in not-DPMI mode are fault.


But probably the fault was posting some funny stuff in the reply 16 without millions of reservations ::)
Title: Re: Reg16 or reg32??
Post by: Antariy on September 07, 2013, 08:14:32 PM
Quote from: japheth on September 07, 2013, 05:02:17 PM
I'm a nitpicker, so I'll have to slightly correct some of the previous statements  :icon_mrgreen:

Anyway your input was like a synopsis on the topic :t
Title: Re: Reg16 or reg32??
Post by: Gunther on September 07, 2013, 08:54:09 PM
Quote from: Antariy on September 07, 2013, 08:14:32 PM
Anyway your input was like a synopsis on the topic :t

good synopsis and by the way it has not much to do with Korinthenkackerei.

Gunther

Title: Re: Reg16 or reg32??
Post by: Antariy on September 07, 2013, 09:54:28 PM
Hi Gunther :biggrin:

Quote from: Gunther on September 07, 2013, 08:54:09 PM
Korinthenkackerei.

May you explain what means this word?
Title: Re: Reg16 or reg32??
Post by: nidud on September 07, 2013, 10:50:51 PM
deleted
Title: Re: Reg16 or reg32??
Post by: Gunther on September 08, 2013, 08:01:30 PM
Hi Alex,

Quote from: Antariy on September 07, 2013, 09:54:28 PM
Hi Gunther :biggrin:

Quote from: Gunther on September 07, 2013, 08:54:09 PM
Korinthenkackerei.

May you explain what means this word?

of course. It's the German translation of nitpcker or also nit-picker. One can translate it as:

Korinthenkacker or Krümelkacker or Erbsenzähler or Beckmesser. See also: that description. (https://de.wikipedia.org/wiki/Korinthenkacker)

Sinsi,

Quote from: nidud on September 07, 2013, 10:50:51 PM
Sorry, I'm a nitpicker too  :lol:

A nit is a louse (laus) egg (eizelle)
Korinthe – Corinthian, piching grapes; dehydrated: currant (a raisin)

Since a grape is somewhere between a "kokosnuss" and a nit
a more correct word should then be Lauseizellekackerei

The trick is that you can't translate some phrases one to one (see my description above).

Gunther
Title: Re: Reg16 or reg32??
Post by: nidud on September 08, 2013, 10:07:54 PM
deleted
Title: Re: Reg16 or reg32??
Post by: Antariy on September 09, 2013, 11:09:44 AM
Thank you for explanations, Gunther and nidud :biggrin:
Title: Re: Reg16 or reg32??
Post by: Gunther on September 10, 2013, 04:42:12 AM
Hi Alex,

Все в порядке моего друга.

Gunther
Title: Re: Reg16 or reg32??
Post by: Rockphorr on September 10, 2013, 04:23:19 PM
Quote from: Gunther on September 10, 2013, 04:42:12 AM
Hi Alex,

Все в порядке моего друга.

Gunther

It is not correct.

Все в порядке, мой друг. It's ok, my friend.
or
Все в порядке у моего друга. My friend is (feels) ok.

Title: Re: Reg16 or reg32??
Post by: Antariy on September 10, 2013, 05:06:33 PM
Quote from: Rockphorr on September 10, 2013, 04:23:19 PM
Quote from: Gunther on September 10, 2013, 04:42:12 AM
Hi Alex,

Все в порядке моего друга.

Gunther

It is not correct.

Все в порядке, мой друг.


I would like to talk in German as good as Gunther does this in Russian ;-)
Title: Re: Reg16 or reg32??
Post by: Gunther on September 11, 2013, 02:56:56 AM
Alex,

Quote from: Antariy on September 10, 2013, 05:06:33 PM
I would like to talk in German as good as Gunther does this in Russian ;-)

thank you молодец.

Gunther
Title: Re: Reg16 or reg32??
Post by: nidud on September 11, 2013, 04:49:20 AM
deleted
Title: Re: Reg16 or reg32??
Post by: Gunther on September 11, 2013, 05:19:07 AM
Hi nidud,

молодец: devil of a fellow or hotshot or one hell of a guy.

That would be the right translation, I suppose.

Gunther