0

我是组装新手,告诉我这有什么问题,我不知道如何解决这个问题。

section    .text
    global _start   
_start:             
    mov edx,len     
    mov ecx,msg     
    mov ebx,1       
    mov eax,4       

    mov eax,1               

section .data
msg db 'Hello, world!', 0xa  ;
len equ $ - msg     ;
4

1 回答 1

3

如前所述,您的程序显然缺少系统调用。

在 Windows 下(就您为 Windows 生成 .EXE 文件而言)没有直接的系统调用。相反,您必须调用 Windows 附带的 DLL 中的函数。

例子:

mov ecx,len
push ecx
mov ecx,msg
push ecx
mov ecx,1
push ecx
call _write
add esp,12

在 32 位窗口(或在 64 位窗口中运行的 32 位程序)中,基本上有两种类型的函数:stdcall (= WINAPI, CALLBACK, PASCAL) 和 cdecl。

对于这两种类型的函数,参数都必须在堆栈中(第一个参数必须在 ESP+0,第二个参数必须在 ESP+4,依此类推)所以你“推送”参数,而最后一个参数首先被推送(在示例“1”是第一个,“len”是最后一个)。函数的结果(如果有)在 EAX 寄存器中返回(只要它不是浮点值)。

然后调用在 DLL 中定义的函数。最后,该函数将执行系统调用,但是此系统调用可能是特定于版本的!你不必关心这个。

在“stdcall”函数的情况下,该函数将从堆栈中删除参数。(对于具有可变数量参数的函数 - 如 wsprintf - 仅删除强制参数。)在汇编程序中,此类函数被命名为:

_Name@nnn

而“Name”是 C 语言中已知的函数的名称,而 nnn 是将从堆栈中删除的字节数。大多数低级 Windows 函数都是 stdcall 函数。请注意,使用字符串的函数通常以“A”结尾表示 ASCII,或以“W”结尾表示 UNICODE 字符串。您通常使用“A”变体。示例:调用函数“MessageBox”:

(push 4 arguments)
call _MessageBoxA@16

大多数 C 标准库函数都是“cdecl”——参见上面的“write”示例。Cdecl 函数不会调整堆栈指针,因此您必须在“call”指令之后添加“add esp,nnn”。该名称只需在下划线后添加 C 函数名称即可(例如“write()”->“call _write”)。

于 2013-10-24T17:01:43.337 回答