将 yasm 代码(Intel 风格)移植到 gas(AT&T 风格)

Porting yasm code (Intel style) to gas (AT&T style)

我正在尝试了解汇编 x86 32 位中的字符串,但最近从 yasm 切换到 gas 并尝试翻译源文件顺便说一句,我使用了 xorpd 代码,你可以看到 here 我看到了一些 AT&T 语法并尝试翻译 include file 但是我没有翻译它我不知道问题出在哪里,如果有人可以告诉我我的代码中的问题在哪里。

strings.s

.include 'fn.s'

.extern exit

ARRLEN = 5 /* equivalent to .set ARRLEN, 0x5 */

.data /* data section equivalent to .section .data */

    saar: .long 3,5,8 /* array of 32bit integers */
    daar: .fill ARRLEN, 4, 0 /* array of 32bit integers 4 bytes is size it's in format of
.fill repeat, size, value

i used it to intialize the array ARRLEN times with value 0*/

.text /* text section equivalent to .section .text */

.globl _start /* for ld compatibility reasons. equivalent to .global main */

_start:
    movl  ARRLEN, %ecx
    movl  $saar, %esi
    xor   %eax, %eax

_par:
    call  read_hex
    stosl
    loop  _par

    push  [=10=]
    call  exit

fn.s

.data 

hex_new:  .asciz "%x\n"
hex_:     .asciz "%x"
dec_:     .asciz "%d"
dec_new:  .asciz "%d\n"
str_:     .asciz "%s"
new_:     .asciz "\n"
delim:    .asciz "========\n"

.text

print_eax:
    pushal
    push    %eax
    push    $hex_new
    call    printf
    add     , %esp
    popal
    ret

print_eax_dec:
    pushal
    push    %eax
    push    $dec_new
    call    printf
    add     , %esp
    popal
    ret

print_delimiter:
    pushal
    mov     $delim, %eax
    push    %eax
    call    printf
    add     , %esp
    popal
    ret

read_line:
    pushal
    push    %ecx
    push    %edi
    push    [=11=]
    call    read
    add     , %esp 
    xor     %edx, %edx
    movb    [=11=], (%edi,%eax)
    popal
    ret

read_hex:
    push    %ebp
    mov     %esp, %ebp
    sub     , %esp
    push    %ebx
    push    %ecx
    push    %edx

    lea -4(%ebp),%ebx
    push    %ebx
    push    $hex_
    call    scanf
    add     , %esp
    movl    (%ebx), %eax

    pop     %edx
    pop     %ecx
    pop     %ebx
    leave
    ret

read_dec:
    push    %ebp
    movl %esp, %ebp
    subl , %esp
    lea -4(%ebp),%ebx
    pusha
    push    %ebx
    push    $dec_
    call    scanf
    add , %esp
    popa
    movl (%ebx), %eax
    leave
    ret

print_str:
    pushal
    push    %esi
    call    printf
    add , %esp
    popal
    ret

print_eax_binary:
    pushal
    movl , %ecx /* We print 32 digits. */

.print_digit:
        rol , %eax
        mov %eax,%edx
        and , %edx

        push %ecx
        push %eax

        push %edx
        push $hex_
        call printf
        add , %esp

        pop %eax
        pop %ecx

        loop .print_digit
    push $new_
    call printf
    add , %esp
    popal
    ret

编译失败。

$ gcc-9 -m32 strings.s -o strings
strings.s: Assembler messages:
strings.s:1: Error: missing string

第一行有问题。 GAS 要求所有字符串(包括文件名)为 double-quoted.

.include "fn.s" 不是 'fn.s' 单引号。


GAS 不接受像 'abc' 这样的 multi-character 字符文字作为数字文字 ,就像 YASM 和 NASM 那样。事实上,它完全破坏了解析并打印无意义的错误消息。

.string 'abcd'

.include 'fn.s'


mov $'a', %eax
mov $'ab', %ax
.long 'abc'
strings.s: Assembler messages:
strings.s: Warning: end of file not at end of a line; newline inserted
strings.s:1: Error: junk at end of line, first unrecognized character is `9'
strings.s:2: Error: missing string
strings.s:5: Error: backward ref to unknown label "97:"
strings.s:5: Error: junk `44%ax' after expression
strings.s:5: Error: number of operands mismatch for `mov'
strings.s:6: Error: backward ref to unknown label "97:"
strings.s:6: Error: junk at end of line, first unrecognized character is `c'

请注意,第 5 行是空白的,文件 以换行符结尾(但它位于包含单引号的行的末尾。)


Single-character 文字作为整数工作,如 add $'0', %eax.long 'b'.

或在 .intel_syntax noprefix 中,如 add eax, '0'


你应该使用 .intel_syntax noprefix

主要是将 OFFSET 放入 mov reg, symbol(使其成为 mov reg, OFFSET symbol)以获得 mov-immediate 编码,并移植指令。 error-prone 比手动将所有内容更改为 AT&T 语法更容易和更少。