使用 masm32 进行汇编编码
Assembly coding with masm32
在汇编编码中,使用 masm32。
我如何将一个值放入一个变量中,该变量不是在 .data 段中定义的,而是通过 LOCAL decleration 定义的?
千:
.486
.model flat, stdcall
option casemap :none
include \masm32\include\windows.inc
include \masm32\macros\macros.asm
include \masm32\include\masm32.inc
include \masm32\include\gdi32.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\masm32.lib
includelib \masm32\lib\gdi32.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
.data
.code
start:
call main
exit
main proc
LOCAL dewit:DWORD
mov dewit, 0
print dewit
ret
main endp
end start
我试过这样的事情:
Mov dewit, 0
没用。但是,这段代码:
Mov dewit, input("enter a number")
确实给它赋值了。
有人吗?
** LOCAL 减速只能在一个过程中
您可以使用调试器找到它。这是从调试器查看的代码的开头:
CPU Disasm
Address Command Comments
00401000 CALL 0040100C ; call main
00401005 PUSH 0 ; /ExitCode = 0
00401007 CALL <JMP.&kernel32.ExitProcess> ; \KERNEL32.ExitProcess
0040100C PUSH EBP ; main
0040100D MOV EBP,ESP
0040100F ADD ESP,-4
00401012 MOV DWORD PTR SS:[LOCAL.1],0 ; dewit = 0
00401019 PUSH DWORD PTR SS:[LOCAL.1] ; /Arg1 => 0
0040101C CALL 00401024 ; print
00401021 LEAVE
00401022 RETN
所以 print
被调用(记住,print
是一个宏,所以它在编译后展开)。记住你将 0 推到 print
:
CPU Disasm
Address Command Comments
00401024 PUSH EBP ; print (guessed Arg1)
00401025 MOV EBP,ESP
00401027 ADD ESP,-0C
0040102A PUSH -0B ; /StdHandle = STD_OUTPUT_HANDLE
0040102C CALL <JMP.&kernel32.GetStdHandle> ; \KERNEL32.GetStdHandle
00401031 MOV DWORD PTR SS:[LOCAL.1],EAX
00401034 PUSH DWORD PTR SS:[Arg1] ; /Arg1 => [Arg1] *** push 0 ***
00401037 CALL 00401060 ; \so.00401060
参见第 0x00401034
行,0 被推送为调用的参数。
我们来看代码:
CPU Disasm
Address Command Comments
00401060 MOV EAX,DWORD PTR SS:[Arg1] ; eax = 0
00401064 LEA EDX,[EAX+3]
00401067 PUSH EBP
00401068 PUSH EDI
00401069 MOV EBP,80808080
0040106E /MOV EDI,DWORD PTR DS:[EAX] ; trying to dereference [0]...
代码试图读取地址 0(又名 NULL 指针错误),这是一个很大的问题。
看macros.asm
中的print
宏,好像这个宏没有做任何格式化,那你应该用printf
.
您的代码已修复(printf
宏需要 msvcrt.inc
和 msvcrt.lib
,它仍然在 macros.asm
中定义):
.486
.model flat, stdcall
option casemap :none
include \masm32\include\windows.inc
include \masm32\include\msvcrt.inc
include \masm32\macros\macros.asm
include \masm32\include\masm32.inc
include \masm32\include\gdi32.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\msvcrt.lib
includelib \masm32\lib\masm32.lib
includelib \masm32\lib\gdi32.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\masm32.lib
.data
format_string db "value: %d", 0
.code
start:
call main
exit
main proc
LOCAL dewit:DWORD
mov dewit, 0
print "printing value: "
printf ("value: %d", dewit)
ret
main endp
end start
大致相同的代码,没有任何包含:
; compile and link with:
; ml test.asm /link /subsystem:console /defaultlib:kernel32.lib /defaultlib:msvcrt.lib
.686
.model flat, stdcall
option casemap: none
ExitProcess PROTO STDCALL :DWORD
externdef _imp__printf:PTR c_msvcrt
crt_printf equ <_imp__printf>
.data
fmt db "value: %d", 0
.code
start:
call MyFunc
invoke ExitProcess, 0
ret
MyFunc proc
LOCAL foo:DWORD
mov foo, 42
push foo
push offset fmt
call crt_printf
ret
MyFunc endp
end start
我也完全同意@Jester:
Also, consider not using helper features until you can do it by hand
too, and understand what the assembler is doing
宏很棒,但除非您能理解它们的作用并手动实现相同的功能,否则您应该避免使用它们。他们向初学者隐藏了太多东西。
因为您正在使用 MASM32 如果您尝试打印出 32 位值,请尝试使用 str$
:
print str$(dewit)
这会将内存位置 dewit
处的 32 位值转换为字符串,并在控制台上打印该字符串。这也适用于立即值:
print str$(100)
还有一个寄存器:
print str$(eax)
如果您想打印无符号值,也可以使用 $ustr
。
这些宏在 高级宏 帮助中进行了描述 MASM32 SDK
在汇编编码中,使用 masm32。
我如何将一个值放入一个变量中,该变量不是在 .data 段中定义的,而是通过 LOCAL decleration 定义的?
千:
.486
.model flat, stdcall
option casemap :none
include \masm32\include\windows.inc
include \masm32\macros\macros.asm
include \masm32\include\masm32.inc
include \masm32\include\gdi32.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\masm32.lib
includelib \masm32\lib\gdi32.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
.data
.code
start:
call main
exit
main proc
LOCAL dewit:DWORD
mov dewit, 0
print dewit
ret
main endp
end start
我试过这样的事情:
Mov dewit, 0
没用。但是,这段代码:
Mov dewit, input("enter a number")
确实给它赋值了。
有人吗?
** LOCAL 减速只能在一个过程中
您可以使用调试器找到它。这是从调试器查看的代码的开头:
CPU Disasm
Address Command Comments
00401000 CALL 0040100C ; call main
00401005 PUSH 0 ; /ExitCode = 0
00401007 CALL <JMP.&kernel32.ExitProcess> ; \KERNEL32.ExitProcess
0040100C PUSH EBP ; main
0040100D MOV EBP,ESP
0040100F ADD ESP,-4
00401012 MOV DWORD PTR SS:[LOCAL.1],0 ; dewit = 0
00401019 PUSH DWORD PTR SS:[LOCAL.1] ; /Arg1 => 0
0040101C CALL 00401024 ; print
00401021 LEAVE
00401022 RETN
所以 print
被调用(记住,print
是一个宏,所以它在编译后展开)。记住你将 0 推到 print
:
CPU Disasm
Address Command Comments
00401024 PUSH EBP ; print (guessed Arg1)
00401025 MOV EBP,ESP
00401027 ADD ESP,-0C
0040102A PUSH -0B ; /StdHandle = STD_OUTPUT_HANDLE
0040102C CALL <JMP.&kernel32.GetStdHandle> ; \KERNEL32.GetStdHandle
00401031 MOV DWORD PTR SS:[LOCAL.1],EAX
00401034 PUSH DWORD PTR SS:[Arg1] ; /Arg1 => [Arg1] *** push 0 ***
00401037 CALL 00401060 ; \so.00401060
参见第 0x00401034
行,0 被推送为调用的参数。
我们来看代码:
CPU Disasm
Address Command Comments
00401060 MOV EAX,DWORD PTR SS:[Arg1] ; eax = 0
00401064 LEA EDX,[EAX+3]
00401067 PUSH EBP
00401068 PUSH EDI
00401069 MOV EBP,80808080
0040106E /MOV EDI,DWORD PTR DS:[EAX] ; trying to dereference [0]...
代码试图读取地址 0(又名 NULL 指针错误),这是一个很大的问题。
看macros.asm
中的print
宏,好像这个宏没有做任何格式化,那你应该用printf
.
您的代码已修复(printf
宏需要 msvcrt.inc
和 msvcrt.lib
,它仍然在 macros.asm
中定义):
.486
.model flat, stdcall
option casemap :none
include \masm32\include\windows.inc
include \masm32\include\msvcrt.inc
include \masm32\macros\macros.asm
include \masm32\include\masm32.inc
include \masm32\include\gdi32.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\msvcrt.lib
includelib \masm32\lib\masm32.lib
includelib \masm32\lib\gdi32.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\masm32.lib
.data
format_string db "value: %d", 0
.code
start:
call main
exit
main proc
LOCAL dewit:DWORD
mov dewit, 0
print "printing value: "
printf ("value: %d", dewit)
ret
main endp
end start
大致相同的代码,没有任何包含:
; compile and link with:
; ml test.asm /link /subsystem:console /defaultlib:kernel32.lib /defaultlib:msvcrt.lib
.686
.model flat, stdcall
option casemap: none
ExitProcess PROTO STDCALL :DWORD
externdef _imp__printf:PTR c_msvcrt
crt_printf equ <_imp__printf>
.data
fmt db "value: %d", 0
.code
start:
call MyFunc
invoke ExitProcess, 0
ret
MyFunc proc
LOCAL foo:DWORD
mov foo, 42
push foo
push offset fmt
call crt_printf
ret
MyFunc endp
end start
我也完全同意@Jester:
Also, consider not using helper features until you can do it by hand too, and understand what the assembler is doing
宏很棒,但除非您能理解它们的作用并手动实现相同的功能,否则您应该避免使用它们。他们向初学者隐藏了太多东西。
因为您正在使用 MASM32 如果您尝试打印出 32 位值,请尝试使用 str$
:
print str$(dewit)
这会将内存位置 dewit
处的 32 位值转换为字符串,并在控制台上打印该字符串。这也适用于立即值:
print str$(100)
还有一个寄存器:
print str$(eax)
如果您想打印无符号值,也可以使用 $ustr
。
这些宏在 高级宏 帮助中进行了描述 MASM32 SDK