【问题标题】:Assembly coding with masm32使用 masm32 进行汇编编码
【发布时间】:2016-01-15 21:42:17
【问题描述】:

在汇编编码中,使用 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 声明只能在一个过程中

【问题讨论】:

  • mov [dewit], 0 or maybe mov word ptr [dewit], 0`?还要定义“不起作用”。
  • 没有工作 - 即它遇到了错误,我认为.. 程序在那时“停止工作”
  • 信息不够,请提供minimal reproducible example。您可能还想查看生成的汇编代码。此外,在您也可以手动完成之前,请考虑不要使用辅助功能,并了解汇编程序在做什么。
  • 我试过你说的,它没有用..现在为什么所有的downvotes?..
  • 因为您的代码无法按原样编译。 @Jester 要求提供能够重现您的问题的最小代码:minimal 的意思是:我们可以在我们这边编译的代码。例如。您的代码没有通常的标题语句,PrintExit 没有在任何地方定义,也不是 MASM 可以理解的语句。

标签: assembly x86 masm32


【解决方案1】:

您可以使用调试器找到它。这是从调试器查看的代码的开头:

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

您的代码已修复(您需要 msvcrt.incmsvcrt.lib 用于 printf 宏,该宏仍在 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:

另外,在您可以手动操作之前,请考虑不要使用辅助功能 也了解汇编程序在做什么

宏很棒,但除非您能理解它们的作用并手动实现相同的功能,否则您应该避免使用它们。他们在初学者的眼中隐藏了太多东西。

【讨论】:

  • 谢谢!我需要一段时间才能查看你所说的所有内容。但它很有帮助
  • 顺便说一句,你使用哪个调试器?.. @neitsa
【解决方案2】:

由于您使用的是MASM32,如果您尝试打印出一个 32 位值,请尝试使用 str$ 这样做:

print str$(dewit)

这会将内存位置 dewit 的 32 位值转换为字符串,并且该字符串会打印在控制台上。这也适用于即时价值:

print str$(100)

还有一个寄存器:

print str$(eax)

如果您想打印无符号值,也可以使用$ustr

这些宏在MASM32 SDK 附带的高级宏帮助中描述

【讨论】:

  • 酷!现在如果我想打印一个单词怎么办?..因为我看到,正如你所说,它打印了存储在变量中的 number 的值..
  • @daniel 您可以使用类似movsz 指令将字从内存移动到 32 位寄存器,该指令会将 16 位寄存器或内存操作数符号扩展为 32 位寄存器。然后可以将那个 32 位寄存器与 str$ 一起使用
  • @daniel :我可能误解了。你的意思是 WORD 是 16 位的值,还是像“hello there”这样的文本?
  • 要打印出一个字符串,您可以执行类似的操作。在您的 DATA 部分中定义一个字符串,例如 msg1 db "Hello There",0,然后使用 print 打印该字符串。你必须像 print offset msg1 那样做。您需要 offset 关键字,以便打印使用 msg1 的地址,而不是 msg1 指向的地址。您还可以使用 print "hello world" 之类的指令打印字符串
  • 你可以在栈上分配一个字节数组,复制一个字符串,然后用LOCAL locMsg[128]:byte定义一个128字节的缓冲区,fn lstrcpy, addr locMsg, "Hello World"来放置一个字符串,然后从本地变量中打印它,您将使用print addr locMsg(在这种情况下您需要 ADDR 因为 locMsg 是基于函数内部的堆栈)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-08
  • 1970-01-01
相关资源
最近更新 更多