存档

  • AT&T 汇编-12: 内联汇编

    在涉及到一些对硬件的操作或者对性能有极致要求的时候,除了使用汇编函数之外还可以直接在 c 语言里编写汇编代码片段。

    基本格式

    一个最简单的什么都不做的 c 语言程序:

    /* inline.c */
    
    int main()
    {
       asm ("nop");
    
       return 0;
    }
    

    内联汇编使用关键字 asm 表示在 c 语言中使用汇编代码:

    asm ("assembly code");
    

    使用命令

    gcc -S inline.c
    

    转换成汇编语言

        .file   "inline.c"
        .text
    .globl main
        .type   main, @function
    main:
        

    阅读全文…

    2011年7月19日 | 归档: 汇编语言程序设计 | 标签:
  • AT&T 汇编-11: 使用系统调用

    前面使用系统调用 write() 来输入输出。一般来说,在 /usr/include/asm/unistd.h 可以找到可用的系统调用的定义(在我的机器上实际是 unistd_32.h):

    ...
    #define __NR_restart_syscall      0
    #define __NR_exit                 1
    #define __NR_fork                 2
    #define __NR_read                 3
    #define __NR_write                4
    #define __NR_open                 5
    #define __NR_close                6
    ...
    

    定义了系统调用和各自对应的值。

    使用系统调用前要把对应的系统调用值放到 eax 中,再把需要的参数放到对应的位置,最后使用中断 int $0x80 使用系统调用。如果系统调用的参数小于 6 个,参数的顺序依次是:ebx,ecx,edx,esi,edi。如果系统调用的参数超过 6 个,则把参数内存位置的地址放到 …

    阅读全文…

    2011年7月5日 | 归档: 汇编语言程序设计 | 标签:
  • AT&T 汇编-10: 使用函数(2)

    自己定义的汇编函数可以使用任意方式传递参数,但是如果每个函数都以不同方式传递参数则很容易造成混乱,所以一般都遵循 c 语言对参数的处理方式。

    有些通用寄存器被 c 语言用作特殊的用途,如果在函数种需要修改这些寄存器需要把它们保存起来,在退出函数时再恢复原来的值:

    +--------+------------------+
    | 寄存器 |       作用       |
    +--------+------------------+
    |   ebx  |  指向全局偏移表  |
    +--------+------------------+
    |   edi  |    局部寄存器    |
    +--------+------------------+
    |   esi  |    局部寄存器    |
    +--------+------------------+
    |   ebp  | 作为堆栈基址指针 |
    +--------+------------------+
    |   esp  |  

    阅读全文…

    2011年7月1日 | 归档: 汇编语言程序设计 | 标签:
  • AT&T 汇编-10: 使用函数(1)

    很多时候一段实现特定功能的代码可以复用,循环就是一个例子,代码复用更常见的形式是函数。

    # func.s
    
    .section .rodata
    msg:
       .ascii   "This is a message.\n"
    
    .section .text
    
    .type print_msg, @function
    print_msg:
       pushl %eax
       pushl %ebx
       pushl %ecx
       pushl %edx
    
       movl  $4,    %eax
       movl  $1,    %ebx
       movl  $msg,  %ecx
       movl  $19,   %edx
       int   $0x80
    
       popl  

    阅读全文…

    2011年6月23日 | 归档: 汇编语言程序设计 | 标签:
  • AT&T 汇编-9: 位操作

    位操作是针对整数的二进制位进行的。

    左移

    用于左移的指令有两种:sal(向左算术移位)和shl(向左逻辑移位)。它们执行的操作相同,对于有符号和无符号整数的结果也一样。指令有 3 种不同的格式(以shl为例):

    shl   destination
    shl   %cl,  destination
    shl   shift,   destination
    

    destination 可以是 8 位,16 位或 32 位的值,根据不同的长度在 sal/shl 后附加不同的字母区分。第一种格式把 destination 的各个二进制位依次向左移动 1 位;第二种格式把 destination 的各个二进制位依次向左移动寄存器 cl 中指定的位数;第三种和第二种意义一样,只不过移动的位数由 shift 指定。

    左移后,数值右边造成的空位用 0 填充,左边超出数据长度的位(最高有效位)会被暂时存放到进位标志(CF)中。

    # shl.s
    
    .section .rodata
    msg:
       

    阅读全文…

    2011年6月16日 | 归档: 汇编语言程序设计 | 标签:
  • AT&T 汇编-8: 内存变址寻址

    # array.s
    
    .section .rodata
    msg:
       .asciz   "The value is: %d.\n"
    array:
       .int 5, 10, 15, 20, 25
    
    .section .text
    .globl main
    main:
       movl  $0,   %edi
    
    loop1:
       pushl array(, %edi, 4)
       pushl $msg
       call  printf
       addl  $8,   %esp
       inc   %edi
       cmp   

    阅读全文…

    2011年6月8日 | 归档: 汇编语言程序设计 | 标签:
  • AT&T 汇编-7: 跳转标志

    EFLAGS 寄存器包含很多用来表明结果状态的标志,根据这些标志值可以作出不同的跳转。

    CF(carry flag)标志

    # jc.s
    
    .section .rodata
    msg:
       .asciz   "The result is: %d.\n"
    err:
       .asciz   "overflow.\n"
    
    .section .text
    .globl main
    main:
       movw  $55555,  %ax
       movw  $55555,  %bx
       addw  %ax,     %bx
       jc    overflow
    
       pushw $0
       pushw %bx
       pushl $msg
       call  

    阅读全文…

    2011年5月25日 | 归档: 汇编语言程序设计 | 标签:
  • AT&T 汇编-6: 循环

    loop 指令使用 ecx 作为计数器并且在每次执行的时候自动递减 ecx 的值,直到 ecx 为 0。loop 指令的格式是

    loop location
    

    其中 location 是要跳转的程序代码的标签。loop 指令只支持 8 位的偏移量,所以只能进行短跳转(跳转偏移量小于 128 字节)。

    # loop.s
    
    .section .rodata
    msg:
       .asciz   "The value of ecx is %d.\n"
    
    .section .text
    .globl main
    main:
       movl  $5,   %ecx
    

    阅读全文…

    2011年5月19日 | 归档: 汇编语言程序设计 | 标签:
  • AT&T 汇编-5: 分支跳转

    很多时候代码都不是从头到尾顺序依次执行的,往往需要根据条件进行跳转,改变代码的执行流程。

    无条件跳转

    无条件跳转就一条很简单的 jmp 命令:

    jmp   location
    

    其中 location 是要跳转到的代码位置,通常由一个标签表示。标签就是一个标识符后加一个冒号,像一直在使用的 main 和 _start 都是标签。

    # jmp.s
    
    .section .rodata
    msg1:
       .ascii   "I like this mm.\n"
    msg2:
       .ascii   "I like that mm.\n"
    
    .section .text
    .globl _start
    _start:
       movl  $4,      %eax  # system 

    阅读全文…

    2011年5月15日 | 归档: 汇编语言程序设计 | 标签:
  • AT&T 汇编-4: 简单四则运算

    加法

    用于加法的是 add 系列指令。

    # add.s
    
    .section .rodata
    output:
       .asciz "the result is: %d.\n"
    
    .section .text
    .globl main
    main:
       movl  $7,   %eax
       addl  $5,   %eax
       pushl %eax
       pushl $output
       call  printf
       addl  $8,   %esp
    
       pushl $0
       call  exit
    

    add 系列指令的格式是:…

    阅读全文…

    2011年5月10日 | 归档: 汇编语言程序设计 | 标签:
文章标签 ‘AT&T汇编’
  • 当前页 1 / 2
  • 1
  • 2
  • »