• 汇编程序的Hello world


    原文链接:http://www.orlion.ga/989/

    一、汇编程序的Hello world

    x86 AT&T:

    .data  
    msg:  
        .ascii "Hello world, hello AT&T asm!
    "  
        len = . - msg  
      
    .text  
    .global _start  
      
    _start:  
        movl    $len,   %edx    # 显示的字符数  
        movl    $msg,   %ecx    # 缓冲区指针  
        movl    $1, %ebx    # 文件描述符  
        movl    $4, %eax    # 系统调用号,_write  
        int $0x80       # 系统调用  
      
        movl    $0, %ebx    # 传给_exit的参数  
        movl    $1, %eax    # 系统调用号,_exit  
        int $0x80       # 系统调用

    然后汇编链接再执行:

    这段汇编相当于:

    #include <unistd.h>
    char msg[14] = "Hello,world!
    ";
    #define len 14
    
    int main(void)
    {
        write(1, msg, len);
        _exit(0);
    }

        .data段有一个标号msg,代表字符串“Hello,world! ”的首地址,相当于C程序的一个全局变量。在汇编指示.ascii定义的字符串末尾没有隐含的‘’。汇编程序中的len代表一个常量,它的值由当前地址减去符号msg所代表的地址得到,换句话说就是字符串“Hello,world! ”的长度。现在解释一下这行代码中的.,汇编器总是从前到后把汇编代码转换成目标文件,在这个过程中维护一个地址计数器,当处理到每个段的开头时把地址计数器置成0,然后每处理一条汇编指示或指令就把地址计数器增加相应的字节数,在汇编程序中用.可以取出当前地址计数器的值,是一个常量。

        在_start中调了两个系统调用,第一个是write系统调用,第二个是以前讲过的_exit系统调用。在调write系统调用时,eax寄存器保存着write的系统调用号4,ebx、ecx、edx寄存器分别保存着write系统调用需要三个参数。ebx保存着文件描述符,进程中每个打开的文件都用一个编号来标识,成为文件描述符,文件描述符1表示标准输出,对应的C标准I/O库的stdout。ecx保存着输出缓冲区的首地址。edx保存着输出的字节数。write系统调用把从msg开始的len个字节写到标准输出。

        C代码中的write函数是系统调用的包装函数,其内部实现就是把传进来的三个参数分别赋给ebx、ecx、edx寄存器,然后执行movl $4,%eax和int $0x80两指令。这个函数不可能完全用C代码写,因为任何C代码都不会编译生成int指令,所以这个函数有可能完全用汇编写的,也有可能是C用内联汇编写的,甚至是一个宏定义。_exite函数野史如此。

  • 相关阅读:
    JS调试工具
    什么是Web Service?
    win7怎么安装消息队列 MSMQ
    死锁产生的原因及四个必要条件
    项目管理模式之如何去除SVN标记
    AJAX中的请求方式以及同步异步的区别
    敏捷软件开发模型--SCRUM
    堆和栈
    UI产品设计流程中的14个要点
    Android中dp和px之间进行转换
  • 原文地址:https://www.cnblogs.com/orlion/p/5316519.html
Copyright © 2020-2023  润新知