首页
社区
课程
招聘
[翻译]Say hello to x86_64 Assembly [part 6]
2020-1-14 11:01 6258

[翻译]Say hello to x86_64 Assembly [part 6]

2020-1-14 11:01
6258

Say hello to x86_64 Assembly [part 6]

最近在学习x64汇编,在github上面找到了一点学习资料,入门级别的,因为想细致的学习一下,所以顺便久把作者的内容都翻译了一下,也不知道自己翻译的是否合适,请大家看看有问题的地方请批评指正.第一次做翻译,做的不好请大家原谅,

 

作者原文


 

这是Say hello to x86_64 Assembly的第六部分,在这里我们将研究AT&T汇编程序语法。以前我们在所有部分都使用nasm assembler,但是还有其他一些具有不同语法的汇编程序fasm、yasm和其他。正如我在上面写的,我们将研究gas(GNU汇编程序)及其语法和nasm之间的区别。GCC使用GNU汇编程序,因此如果您在汇编程序输出中看到简单的hello world:

 

It is sixth part of Say hello to x86_64 Assembly and here we will look on AT&T assembler syntax. Previously we used nasm assembler in all parts, but there are some another assemblers with different syntax, fasm, yasm and others. As i wrote above we will look on gas (GNU assembler) and difference between it’s syntax and nasm. GCC uses GNU assembler, so if you see at assembler output for simple hello world:

#include <unistd.h>

int main(void) {
    write(1, "Hello World\n", 15);
    return 0;
}

您将看到以下输出:

 

You will see following output:

    .file    "test.c"
    .section    .rodata
.LC0:
    .string    "Hello World\n"
    .text
    .globl    main
    .type    main, @function
main:
.LFB0:
    .cfi_startproc
    pushq    %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    movl    $15, %edx
    movl    $.LC0, %esi
    movl    $1, %edi
    call    write
    movl    $0, %eax
    popq    %rbp
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE0:
    .size    main, .-main
    .ident    "GCC: (Ubuntu 4.9.1-16ubuntu6) 4.9.1"
    .section    .note.GNU-stack,"",@progbits

看起来与nasm不一样的Hello world,让我们看看有些什么不同。

 

Looks different then nasm Hello world, let’s look on some differences.

AT&T 语法

AT&T syntax

Sections

 

我不知道你怎么样,但当我开始编写汇编程序时,通常是从节定义开始的。让我们看一个简单的例子:

 

I don’t know how about you, but when I start to write assembler program, usually I’m starting from sections definition. Let’s look on simple example:

.data
    //
    // 初始化数据定义 initialized data definition
    //
.text
    .global _start

_start:
    //
    // 主程序 main routine
    //

你可以在这里注意到两个小小的区别:
-节定义以开头以.符号
-主程序定义使用.globl,而不是像我们在nasm中那样使用global
gas还使用另一个指令来定义数据:

 

You can note two little differences here:

  • Section definition starts with . symbol
  • Main routine defines with .globl instead global as we do it in nasm

Also gas uses another directives for data defintion:

.section .data
    // 1 byte
    var1: .byte 10
    // 2 byte
    var2: .word 10
    // 4 byte
    var3: .int 10
    // 8 byte
    var4: .quad 10
    // 16 byte
    var5: .octa 10

    // assembles each string (with no automatic trailing zero byte) into consecutive addresses
    str1: .asci "Hello world"
    // just like .ascii, but each string is followed by a zero byte
    str2: .asciz "Hello world"
    // Copy the characters in str to the object file
    str3: .string "Hello world"

操作数顺序使用nasm编写汇编程序时,数据操作的一般语法如下:

 

Operands order When we write assembler program with nasm, we have following general syntax for data manipulation:

mov destination, source

GNU 汇编有着相反的操作方向,即:

 

With GNU assembler we have back order i.e.:

mov source, destination

举例:

 

For example:

;;
;; nasm syntax
;;
mov rax, rcx

//
// gas syntax
//
mov %rcx, %rax

另外,不能在这里使用%symbol注册开始元素。如果使用的是直接操作数,则需要使用$符号:

 

Also you can not here that registers starts with % symbol. If you’re using direct operands, need to use $ symbol:

movb $10, %rax

操作数大小和操作语法

Size of operands and operation syntax

 

有时当我们需要获得部分内存时,例如64寄存器的第一个字节,我们使用以下语法:

 

Sometimes when we need to get part of memory, for example first byte of 64 register, we used following syntax:

mov ax, word [rsi]

在gas中进行此类操作还有另一种方法。我们不在操作数中定义大小,而是在指令中定义大小:

 

There is another way for such operations in gas. We don’t define size in operands but in instruction:

movw (%rsi), %ax

GNU汇编程序有6个操作后缀:

  • b - 1 byte 操作符
  • w - 2 bytes 操作符
  • l - 4 bytes 操作符
  • q - 8 bytes 操作符
  • t - 10 bytes 操作符
  • o - 16 bytes 操作符

GNU assembler has 6 postfixes for operations:

  • b - 1 byte operands
  • w - 2 bytes operands
  • l - 4 bytes operands
  • q - 8 bytes operands
  • t - 10 bytes operands
  • o - 16 bytes operands

这个规则不仅是mov指令,而且还适用于所有其他指令,如addl、xorb、cmpw等…

 

This rule is not only mov instruction, but also for all another like addl, xorb, cmpw and etc…

内存访问

Memory access

 

您可以注意到,我们在前面的示例中使用了()括号,而在nasm示例中使用了[]。要解引用括号中的值,请使用GAS:(%rax),例如:

 

You can note that we used () brackets in previous example instead [] in nasm example. To dereference values in parentheses are used GAS: (%rax), for example:

movq -8(%rbp),%rdi
movq 8(%rbp),%rdi

跳转

Jumps

 

GNU汇编程序支持以下运算符用于远跳转函数调用和跳转:

 

GNU assembler supports following operators for far functions call and jumps:

lcall $section, $offset

远跳转-跳转到位于不同于当前代码段但处于相同权限级别的段中的指令,有时称为段间跳转。

 

Far jump - a jump to an instruction located in a different segment than the current code segment but at the same privilege level, sometimes referred to as an intersegment jump.

注释

Comments

 

GNU汇编程序支持3种类型的注释:

 

GNU assembler supports 3 types of comments:

    # - 单行注释 single line comments
    // - single line comments
    /* */ - 多行注释 for multiline comments

[培训]《安卓高级研修班(网课)》月薪三万计划

收藏
点赞1
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回