Я работал над Язык ассемблера. Шаг за шагом: третье издание , и я нахожусь в заключительной главе "Направляясь к C".Я пытаюсь получить согласованный метод преобразования 32-битного кода, который вызывает функцию библиотеки C (glibc) puts
в моей 64-битной системе Ubuntu.(Я хотел бы проследить последние 50 страниц текста, который, предположительно, углубляется в C [более отвратительные каламбуры], но из сборочной базы, написанной с 32-битным кодом).Код:
SECTION .data ; Section containing initialised data
EatMsg: db "Eat at Joe's!",0
SECTION .text ; Section containing code
extern puts ; Simple "put string" routine from clib
global main ; Required so linker can find entry point
main:
push ebp ; Set up stack frame for debugger
mov ebp,esp
push ebx ; Must preserve ebp, ebx, esi, & edi
push esi
push edi
;;; Everything before this is boilerplate; use it for all ordinary apps!
push EatMsg ; Push address of message on the stack
call puts ; Call clib function for displaying strings
add esp,4 ; Clean stack by adjusting ESP back 4 bytes
;;; Everything after this is boilerplate; use it for all ordinary apps!
pop edi ; Restore saved registers
pop esi
pop ebx
mov esp,ebp ; Destroy stack frame before returning
pop ebp
ret ; Return control to Linux
Предлагаемые команды nasm и linker:
nasm -f elf -g -F stabs eatclib.asm
gcc eatclib.o -o eatclib
Самое близкое приближение к решению, которое я нашел, здесь: Вызовите функции C из64-битная сборка .
Я попытался преобразовать расширенные регистры в rbp
, rsp
и т. Д .;настройте указатель стека на 8 бит вместо четырех после вызова puts
и настройте make-файл, используя:
nasm -f elf64 -g -F dwarf eatclib.asm
и
gcc eatclib.o -o eatclib -m64 -static
, но получили ошибку сегментации.
Мое понимание соглашения о вызовах в C все еще туманно / достаточно сомнительно, так что я не особо углублялся в попытки найти ошибку, когда пытался следовать вместе с отладчиком gdb (обе проблемы только несколькознаком с 32-битными соглашениями и не так много с C).Эта книга предназначена для ознакомления начинающих программистов на ассемблере, у которых практически нет C-фона.
В другом направлении простая программа на C, которая использует put со строкой, создает файл (используя gcc-S
option) из:
.file "SayHello.c"
.text
.section .rodata
.align 8
.LC0:
.string "This is based on an example from C Primer Plus"
.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
leaq .LC0(%rip), %rdi
call puts@PLT
movl $0, %eax
popq %rbp
.cfi_def_cfa 7, 8
ret
Скомпилированный код работал (и я понимаю большую часть этого, за исключением директив .cfi
, что означает .rodata
, и почему газ застрял в этом @PLT
на puts
.) Это, конечно, синтаксис газа и текст, который я в основном использую с функциями NASM.
Я также пытался использовать загрузчик вместо gcc со строкой, найденной на стр. 89 из Professional Assembly Language (Ричард Блюм)
ld -dynamic-linker /lib/ld-linux.so.2 -o eatclib -lc eatclib.o
, но в итоге возникают довольно типичные ошибки компоновщика, с которыми я сталкивался раньше:
ld: i386 architecture of input file `eatclib.o' is incompatible with i386:x86-64 output
ld: warning: cannot find entry symbol _start; defaulting to 0000000000400250
makefile:2: recipe for target 'eatclib' failed
Я пыталсяпередача опции -m32
компоновщику тоже безрезультатна.
В любом случае, я ищу предложения, которые будут работать.В своем поиске я видел примеры, когда люди предлагали использовать apt-get
и устанавливать новые (на самом деле старые) библиотеки, но, похоже, они эффективно поглощают всю 64-битную систему - что выглядит довольно радикально, когда я смог запустить предыдущий32-битный код с опцией -melf_i386
, передаваемой компоновщику).