首页 > 程序人生 > 80×86汇编基础(四)——Hello world!

80×86汇编基础(四)——Hello world!

学习过程序设计语言的朋友,应该不会对Hello world感到陌生,相信大部分朋友跟我一样,刚开始接触某种语言,写的第一个程序就是Hello world。学习C、C++、Java这些高级语言如此,学习Bash、Php、Python这些script语言亦是如此。本篇是8086汇编系列的第四篇,通过前面三篇的介绍,我们已经具备了写Hello world的基本知识,本篇就让我们来看看用8086的汇编,如何实现Hello world。在开始之前,需要说明一下,因为我个人的开发环境是在Linux下,所以本文采用了AT&T的汇编语法。关于AT&T与Intel语法的差异,我在第三篇中已经有所介绍,不了解的朋友可以先看第三篇的内容。在今后本系列的文章中,如果没有特别的说明,我所采用的环境都是Ubuntu 11.04 i386, 内核版本2.6.38-8-generic, GCC版本4.5.2, GDB版本7.2。
下面我提供两个版本的Hello world的实现,通过这两个例子,来说明一些在Linux下用8086汇编进行程序设计的基本过程与一些注意事项:

  • 1. 通过系统调用write实现
  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    
    .section .data
    hello:
        .ascii "Hello world!\n"
     
    .section .bss
     
    .section .text
    .global _start
    _start:
        movl $4, %eax
        movl $1, %ebx
        movl $hello, %ecx
        movl $13, %edx
        int $0x80
        movl $1, %eax
        movl $0, %ebx
        int $0x80

    我们先来看看运行的情况,然后再分析上面的程序:

    1
    2
    3
    4
    
    wuzesheng@ubuntu:~/work/as$ as hello1.s -o hello1.o
    wuzesheng@ubuntu:~/work/as$ ld hello1.o -o hello1
    wuzesheng@ubuntu:~/work/as$ ./hello1 
    Hello world!

    上面的代码,如我们所愿,完成了Hello world的功能,下面我们来逐行分析一下上面的代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
    1-4行,为data section, 定义了一个字符串hello, 内容为"Hello world!\n"
    5-6行,为bss section, 内容为空
    7-17行,为text section, 这部分即是程序的主体部分
    8行:声明程序入口_start为全局可见
    9行:定义程序入口_start标签
    10行:将4赋给eax寄存器(4号系统调用为write)
    11行:将1赋给ebx寄存器(1为标准出错的fd)
    12行:将hello的地址赋给ecx寄存器
    13行:将hello串的长度赋给edx寄存器
    14行:通过0x80软中断调用4号系统调用write(类似write(stdout, hello, 13))
    15-17行:以参数0,调用1号系统调用exit,退出程序
  • 2. 通过C函数printf实现
  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    
    .section .data
    hello:
        .ascii "Hello world!\n"
     
    .section .bss
     
    .section .text
    .global _start
    _start:
        push $hello
        call printf
        addl $4, %esp
        push $0
        call exit

    我们先来看看程序运行的情况,然后再对程序进行分析:

    1
    2
    3
    4
    
    wuzesheng@ubuntu:~/work/as$ as hello2.s -o hello2.o
    wuzesheng@ubuntu:~/work/as$ ld -dynamic-linker /lib/ld-linux.so.2 -lc hello2.o -o hello2
    wuzesheng@ubuntu:~/work/as$ ./hello2
    Hello world!

    同样,上面的程序,也如我们所愿,完成了Hello world的功能。下面我们对程序进行分析:

    1
    2
    3
    
    1-4行,为data section, 定义了字符串hello
    5-6行,为bss section, 内容为空
    7-14,为text section, 是程序的主体,该部分主要是调用了printf打印了hello, 然后调用了exit退出程序,程序本身比较简单,这里就不再赘述

    以上即是用8086来实现Hello world的两种方式,程序本身都比较简单,但是,这里需要补充说明的一点是,通过C函数来实现的Hello world, 在链接的时候,需要把c函数库链入,链接器才能正确找到printf和exit函数的地址,相信细心的朋友已经注意到了,两种不同的实现,用as汇编的过程是一样的,但是用ld进行链接的过程是不一样的,这里用了GNU的动态链接器ld-linux.so.2,链接了libc.so。另外,关于data/bss/text这些段,相信学过程序的朋友都有所了解的,我在这里再简单的说一下,data section是用来存放初始化好的全局变量的区域,bss section是用来存储没有初始化,或者初始值为0的全局变量的区域,而text sextion是用来存储程序代码本身的区域。

    1. 2011年7月5日18:05 | #1

      这个不错啊~对汇编是只能大致看看,不会写。。

    1. 本文目前尚无任何 trackbacks 和 pingbacks.
    您必须在 登录 后才能发布评论.