【问题标题】:Assembly, hello world question大会,你好世界问题
【发布时间】:2011-03-23 12:17:46
【问题描述】:

我正在 Linux 上学习 asm (noobuntu 10.04) 我得到了以下代码:http://asm.sourceforge.net/intro/hello.html

section .text
global _start ;must be declared for linker (ld)

_start: ;tell linker entry point

mov edx,len ;message length
mov ecx,msg ;message to write
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel

mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel

section .data

msg db 'Hello, world!',0xa ;our dear string
len equ $ - msg ;length of our dear string

这是一个简单的hello world。在 Linux 上运行 + 直接调用内核(显然)。 谁能解释一下这里到底发生了什么?我认为它读取 eax 和 ebx 处理器寄存器和 ecx、edx 数据中的整数,并在调用内核时定义系统调用。如果是这样,当调用 int 0x80 时,不同的整数组合是否定义了不同的系统调用?

我不擅长手册页,但我已经阅读了我能找到的所有相关手册,是否有任何手册页告诉我哪些组合定义了哪些系统调用?

感谢任何帮助。逐行解释将是惊人的...... -提前致谢 杰里米

【问题讨论】:

    标签: assembly x86 linux-kernel system-calls


    【解决方案1】:

    当您调用int 0x80 时,内核会查看eax 寄存器的值以确定您要调用的函数(这是“系统调用号”)。根据该数字,其余寄存器被解释为表示特定事物。 sys_write 调用期望寄存器设置如下:

    • eax 包含 4 个
    • ebx 包含文件描述符
    • ecx 包含要写入的数据的地址
    • edx 包含字节数

    如需更多详细信息,请参阅Linux System Calls

    【讨论】:

    • 非常感谢,这是我的怀疑和帮助......你能告诉我在哪里可以了解更多信息吗?这些系统调用整数是否在手册页中?
    • 你必须深入研究 Linux 源头文件才能找到系统调用号。目前我手边没有一台 Linux 机器,所以我不能告诉你确切的位置,但它类似于内核源代码树中的 include/asm/syscall.h
    【解决方案2】:

    系统调用太多,无法为每个系统调用不同的汇编语言指令。

    相反,您调用 TRAP 指令。 eax 的值决定了将调用哪个系统调用。其他寄存器是系统调用的参数。

    系统调用在内核中列出。

    【讨论】:

    • 谢谢。究竟在哪里查看内核中的系统调用?
    【解决方案3】:
    section .text
    global _start ;must be declared for linker (ld)
    

    这只是标题材料,汇编程序的“文本”部分只是机器指令(相对于数据、只读数据和 BSS 部分)。 global 行类似于说 _start 函数是“公共的”。

    _start: ;tell linker entry point
    
    mov edx,len ;message length
    mov ecx,msg ;message to write
    mov ebx,1 ;file descriptor (stdout)
    mov eax,4 ;system call number (sys_write)
    int 0x80 ;call kernel
    

    从 cmets 中我们知道我们正在查看 sys_write 函数,因此我们可以通过 man 2 write 获取详细信息。 C 原型提供以下参数:fd*bufcount。从 %ebx 开始,我们看到这些匹配(%ebx = fd,%ecx = 要写入的字符串,%edx = 字符串的长度)。然后,由于我们是用户进程,我们必须要求内核执行输出。这是通过 SYSCALL 接口完成的,write() 函数(显然)被赋予了数字 4。INT 0x80 是一个调用 Linux 内核的 SYSCALL 例程的软件中断。

    您可以在 Linux 头文件中找到所有系统调用的实际数量(假设您已安装它们)。在我的系统上,我检查了/usr/include/sys/syscall.h 导致/usr/include/asm/unistd.h,然后进入/usr/include/asm-i386/unistd.h。在哪里(我看到了),#define __NR_write 4

    mov eax,1 ;system call number (sys_exit)
    int 0x80 ;call kernel
    

    与上一段的最后两行一样,这只是加载系统调用 ID 并执行软件中断以退出程序(删除它的内存映射和清理)。

    section .data
    
    msg db 'Hello, world!',0xa ;our dear string
    len equ $ - msg ;length of our dear string
    

    这是数据部分,它只是描述了我们在程序中使用的变量。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-11-19
      • 2016-05-23
      • 1970-01-01
      • 2015-03-02
      • 2015-01-13
      • 1970-01-01
      相关资源
      最近更新 更多