News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Older Registers and Print macro

Started by zekyr, July 30, 2011, 06:29:10 PM

Previous topic - Next topic

zekyr

Hello! I'm new to the forum; I've got just a little bit of experience with hcs12 asm but I'm completely new to all this and was hoping for a little help! I also wanted to get my first post out of the way

I installed the MASM32 sdk and fired up Qeditor and am having a bit of trouble understanding why this will compile and run correctly

test proc
    mov ebx, 10
FARK:   
    print str$(ebx),10,13
    dec ebx
    jnz FARK
    ret
test endp

but when i change the registers to say

test proc
    mov bl, 10
FARK:   
    print str$(bl),10,13
    dec bl
    jnz FARK
    ret
test endp

it will compile run and hang

I thought BL was a byte wide; and im wondering where i went wrong with this.

MichaelW

The problem is that the str$ macro, like other similar macros, is coded to take a DWORD parameter.

; ----------------------------------------------------------
  ; function position macros that takes a DWORD parameter and
  ; returns the address of the buffer that holds the result.
  ; The return format is for use within the INVOKE syntax.
  ; ----------------------------------------------------------
    str$ MACRO DDvalue
      LOCAL rvstring
      .data
        rvstring db 20 dup (0)
        align 4
      .code
      invoke dwtoa,DDvalue,ADDR rvstring
      EXITM <ADDR rvstring>
    ENDM


You can correct the problem by extending BL to 32 bits:

tester proc
    mov bl, 10
FARK:
    movzx eax, bl
    print str$(eax),10,13
    dec bl
    jnz FARK
    ret
tester endp


I changed your procedure name because TEST is the name of an instruction.


eschew obfuscation

dedndave

best to use EBX anyways
DEC BL is 2 bytes
DEC EBX is 1 byte   :P

i am surprised it assembled with the proc named "test", though   :bg

zekyr

That makes sense!


also it didn't assemble, I gave the procedure a dumb name so I changed it really quickly to test when I posted the code then realized it doesnt assemble with that name =D . Thanks a lot though! By 2 bytes on DEC BL do you mean that instruction assembles into 2 bytes?

dedndave

pretty sure
INC and DEC on a full-size general register are special single-byte opcodes
nice to know, but burned up a lot of opcode space, if you ask me

MichaelW

In greater detail, the problem is that ML 6.14 has a bug that causes it to generate this code:

00000002  68 00000000 R  push   OFFSET ??0019
00000007  6A 00          push   000h
00000009  8A C3          mov    al, bl
0000000B  66| 0F B6 C0   movzx  ax, al
0000000F  66| 50         push   ax
00000011  E8 00000000 E  call   dwtoa


Which is pushing a DWORD followed by a WORD, 6 bytes total. In 32-bit code the stack must be maintained at a minimum 4-byte alignment, and the generated code is failing to do this. If the generated code were like this:

00000002  68 00000000 R  push   OFFSET ??0019
00000007  66| 68 0000    push   WORD PTR 0
0000000B  8A C3          mov    al, bl
0000000D  66| 0F B6 C0   movzx  ax, al
00000011  66| 50         push   ax
00000013  E8 00000000 E  call   dwtoa


Then there would be no problem.


eschew obfuscation

dedndave

huh ?
are you talking about the str$ macro ?

MichaelW

Yes, the disassembly is the generated code for the str$ macro when its arg is BL. Sorry, I should have provided more context.
eschew obfuscation

dedndave

i guess you could dress up those macros to handle byte and word registers
but, i never really need them that way
once in a while, i might do somthing like this...
        print   right$(uhex$(eax),2),32
:bg

MichaelW

Or recode the macro to check the size and handle it accordingly, but I doubt that it's worth the effort. Newer versions of ML may not have this problem - I can't recall testing beyond 6.15.
eschew obfuscation