无法弄清楚如何在 MASM32 中打印数字
Can't figure out how to print a number in 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 F运行ze 所描述:
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
请帮助我克服这些开始的障碍,谢谢!
首先,myvar db 52
放错地方了。当程序启动时,计算机进入 db 52
并将其视为一条指令。其次,0 值(不要说字符)不是 StdOut
的参数,必须位于数据的末尾。 StdOut
需要一个指向零终止字符串的 指针 作为参数。你不能给它一个直接的值,函数仍然会把它当作指针。顺便说一句:请考虑 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 的关键字:"assembly convert integer to 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.
我讨厌问这种基本问题。它让我看起来很懒惰!但是我花了好几个小时查看文档,无论出于何种原因,我都无法在这个小问题上直接转过头来。
我想在屏幕上打印字符“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 F运行ze 所描述:
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
请帮助我克服这些开始的障碍,谢谢!
首先,myvar db 52
放错地方了。当程序启动时,计算机进入 db 52
并将其视为一条指令。其次,0 值(不要说字符)不是 StdOut
的参数,必须位于数据的末尾。 StdOut
需要一个指向零终止字符串的 指针 作为参数。你不能给它一个直接的值,函数仍然会把它当作指针。顺便说一句:请考虑 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 的关键字:"assembly convert integer to 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.