首页 > 解决方案 > 将 yasm 代码(英特尔风格)移植到 gas(AT&T 风格)

问题描述

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

字符串.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  $0
    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     $8, %esp
    popal
    ret

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

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

read_line:
    pushal
    push    %ecx
    push    %edi
    push    $0
    call    read
    add     $12, %esp 
    xor     %edx, %edx
    movb    $0, (%edi,%eax)
    popal
    ret

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

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

    pop     %edx
    pop     %ecx
    pop     %ebx
    leave
    ret

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

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

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

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

        push %ecx
        push %eax

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

        pop %eax
        pop %ecx

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

编译器失败。

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

标签: assemblyx86-64gnu-assembleryasm

解决方案


问题是第一行。 GAS 要求所有字符串(包括文件名)都用双引号引起来。

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


'abc'GAS 也不像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 行是空白的,并且文件确实以换行符结尾(但它位于包含单引号的行的末尾。)


单字符文字作为整数工作,例如add $'0', %eaxor .long 'b'

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


你可能应该使用.intel_syntax noprefix

大多数情况下只是放入OFFSETmov reg, symbol制作它mov reg, OFFSET symbol)以获得 mov-immediate 编码,并移植指令。比手动将所有内容更改为 AT&T 语法要容易得多且不易出错。


推荐阅读