[英]Assembly problem with simple program
我正在尝试从头开始学习汇编。 我已经阅读了很多,但即使是我在参考书中找到的以下简单程序也让我难倒:
section .data
msg db "Hello!", 0xa
len equ $ - msg
section .text
global _start
_start:
move edx, len
move ecx, msg
move ebx, 1
move eax, 4
int 0x80
move ebx, 0
move eax, 1
int 0x80
现在显然这应该打印“你好”。 但我什至不知道在任何阶段发生了什么。 前两个阶段将消息长度和消息放在两个寄存器中,不再使用。 我不明白为什么。
我不知道为什么需要四个不同的寄存器。
int 0x80
是某些(a)类 UNIX 操作系统中用于进行系统调用的机制。
对于这些调用,寄存器用于特定值。 从syscalls
文件:
0 STD NOHIDE { int nosys(void); } syscall nosys_args int
1 STD NOHIDE { void exit(int rval); } exit rexit_args void
2 STD POSIX { int fork(void); }
3 STD POSIX { ssize_t read(int fd, void *buf, size_t nbyte); }
4 STD POSIX { ssize_t write(int fd, const void *buf, size_t nbyte); }
您可以看到数字 4 是write
调用并且需要其他三个参数。 数字 1 是exit
,只需要返回代码。
进行调用时, eax
是您正在进行的系统调用,而ebx
、 ecx
和edx
是三个参数(假设它们都是必需的 - 例如exit
只需要一个)。
因此,您可以按如下方式注释代码:
move edx, len ; length of message (nbyte).
move ecx, msg ; message to print (buf).
move ebx, 1 ; file descriptor 1 (stdout).
move eax, 4 ; write syscall.
int 0x80 ; do it.
move ebx, 0 ; exit code (rval).
move eax, 1 ; exit syscall.
int 0x80 ; do it.
(a)更高版本的 Linux 引入了一个新界面,该界面可以使用不同的方法来提供最佳速度。 例如,如果您使用sysenter
而不是int 0x80
,某些英特尔芯片会快得多。
IIRC int 0x80
指令用于通过使用中断向量来调用系统调用。 在您的示例中, ebx
和eax
中的值用于指定您要调用的系统调用(可能是 stdout 上的打印操作)。
系统调用通过约定知道edx
和ecx
应该包含将要打印的内容。
当您调用系统调用时,“int”助记符会产生系统中断。 它有点“跳转”到系统函数,在这种情况下,它打印输出(取决于 eax)。
此中断使用所有这些寄存器来知道要做什么。 中断读取 eax,检查您想要的功能并使用其他寄存器来执行此操作。
eax 是函数编号,4 表示 sys_write,它将字符串写入流/文件描述符。
现在它知道你想写一些东西到某个地方,然后它使用其他寄存器来处理这些信息。
对于 eax = 4 和 int 0x80,这是其他寄存器的含义:
ebx = 输出(1 = 标准输出)
ecx = 字符串地址
edx = 字符串的长度
你可以阅读这个:
http://www.intel.com/Assets/ja_JP/PDF/manual/253665.pdf
第 6.4 节有一些关于中断和异常的内容。
并且可以开始编写Intel 80x86汇编代码,比较简单易懂,这里有一些链接:
助记符/代码表备忘单: http : //www.jegerlehner.ch/intel/
一些介绍网站: http : //mysite.du.edu/~etuttle/math/8086.htm http://www.malware.org/teaching/assembly.htm
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.