无法弄清楚如何在MASM32中打印数字

时间:2015-02-05 20:54:04

标签: assembly syntax masm32

我讨厌问这些基本问题。它让我看起来像是在懒惰!但是我花了好几个小时查看文档,无论出于什么原因,我都无法在这个小点上直接转过头。

我想打印字符" 4"到屏幕。我可以将其作为字符串,但不是来自ascii值。

以下是工作代码:

include c:\masm32\include\masm32rt.inc
.data
    num4 db "4", 10,0
.code
start:
    invoke StdOut, addr num4
    inkey
    invoke ExitProcess, 0
end start

我只想从那里迈出一步,打印ascii字符52(" 4")。到目前为止,这是我最好的尝试:

include c:\masm32\include\masm32rt.inc
.data
.code
start:
    myvar db 52
    invoke StdOut, myvar
    inkey
    invoke ExitProcess, 0
end start

它可以毫无问题地组装和链接,但是当我运行它时会崩溃。我知道它最后没有0个字符,但是invoke StdOut, myvar,0对StdOut有太多的参数。

我的最终目标是能够打印多位数字,如Alexey Frunze所述:

x86 assembly (masm32) - how to split multi-digit data into individual characters

但是由于我在语法方面遇到了很多麻烦,我正在采取措施。我找到了这个,但它没有解释如何在语法上添加48部分:

x86 assembly - how to show the integer 2, not the second ASCII character

请帮助我克服这些开场障碍,谢谢!

1 个答案:

答案 0 :(得分:5)

首先,myvar db 52位于错误的位置。程序启动时,计算机进入db 52并将其视为指令。其次,0值(不要说字符)不是StdOut的参数,必须位于数据的末尾。 StdOut需要将指针作为参数作为零终止字符串。你不能给它一个直接的值,函数会把它作为指针。 BTW:考虑StdOut是MASM32的一个功能,而不是Windows内核的功能。您的程序应如下所示:

include c:\masm32\include\masm32rt.inc
.data
    myvar db 52, 0
.code
start:
    invoke StdOut, ADDR myvar
    inkey
    invoke ExitProcess, 0
end start

在使用' StdOut'输出字符串之前,首先要构建一个字符串。如果您没有字符串而是数字,则必须将其转换为字符串(Google的关键字:"程序集将整数转换为ascii")。诀窍是重复将数字除以10并存储余数。另一个技巧是使用MASM32宏。

INCLUDELIB C:\masm32\lib\masm32.lib
INCLUDE C:\masm32\include\masm32rt.inc

.DATA
    decimalstr db 16 DUP (0)
    myvar db 52

.CODE

start PROC

    movzx eax, myvar         ; Load an 8-bit-byte into a 32-bit-register
    lea edi, decimalstr      ; Load the address of decimalstr
    call EAX_to_DEC
    invoke StdOut, addr decimalstr

    movzx eax, myvar
    printf ("\nAnd the lazy MASM32 way: %u\n",eax)

    invoke ExitProcess, 0
start ENDP

EAX_to_DEC PROC             ; ARG: EDI pointer to string buffer
    mov ebx, 10             ; Divisor = 10
    xor ecx, ecx            ; ECX=0 (digit counter)
  @@:                       ; First Loop: store the remainders
    xor edx, edx
    div ebx                 ; EDX:EAX / EBX = EAX remainder EDX
    push dx                 ; push the digit in DL (LIFO)
    add cl,1                ; = inc cl (digit counter)
    or  eax, eax            ; AX == 0?
    jnz @B                  ; no: once more (jump to the first @@ above)
  @@:                       ; Second loop: load the remainders in reversed order
    pop ax                  ; get back pushed digits
    or al, 00110000b        ; to ASCII
    stosb                   ; Store AL to [EDI] (EDI is a pointer to a buffer)
    loop @B                 ; until there are no digits left
    mov byte ptr [edi], 0   ; ASCIIZ terminator (0)
    ret                     ; RET: EDI pointer to ASCIIZ-string
EAX_to_DEC ENDP

END start

另请查看here