Как-то решил я поробывать перейти с MASM на YASM. Наверное отому, что уже долго использую линукс.
Так вот, у меня возникли вопросы, на которые, я думаю, мне помогут найти ответы здесь.
yasm -f elf64 -g stabs pr.asm -o pr.o
gcc pr.o -o pr
Транслируется и линкуется нормально, но: 1. Возникает ошибка сегментации при вызывое функции puts 2. gdb не правильно отображает точки остановок в псевдоокошке свверху, где отображается код, если запустить gdb c параметром -tui
Вот код программы (она пока ничего не делает):
BITS 64
CPU Bulldozer
extern puts
global main
;;--------------------------------------------------------
;секция инициализированных переменных
SECTION .data
promt1: db "Starting", 0Ah, 0h
promt2: db "Result:", 0h
promt3: db "Allocation error!", 0Ah, 0h
str_funloaded: db "Loaded overlay function: ", 0h
str_exit: db "Bye!", 0Ah, 0h
str_calling: db "Calling overlay function...", 0Ah, 0h
nline: db 0Ah, 0h
o_sum: db "o_sum.bin", 0 ;путь к программе
o_div: db "o_div.bin", 0
o_mul: db "o_mul.bin", 0
o_sub: db "o_sub.bin", 0
src_str: db "10 + 20", 0
;----------------------------------------------------------
;секция сегмент подгрузки оверлейных функций
SECTION .bss
ostart: resb 10
;----------------------------------------------------------
;исполняемы код программы
SECTION .text
; **********************************************
;подсчет длины строки
; вход: rdx смещение строки в ds
; выход: rcx длина строки
astrlen:
xor rcx, rcx
push rbx
mov rbx, rdx ;помещаем адрес строки в ebx
strlen_start:
cmp byte [rbx], 0 ;сравниваем текущий символ строки с 0 символом
je strlen_exit
inc rbx ;увеличиваем счетчик
inc rcx
jmp strlen_start
strlen_exit:
pop rbx
ret
; ************************************************
; печать строки
print:
push rax
push rbx
push rcx
push rdx
;подготовка к системному вызову write
;ssize_t write(int fildes, const void *buf, size_t nbyte);
mov rax, 4
;помещаем в ebx stdout fd
mov rbx, 1
mov r8, rdx
call astrlen
mov rdx, rcx
;в ecx помещаем адрес строки для печати
mov rcx, r8
;вызов системного прерывания linux
int 80h
pop rdx
pop rcx
pop rbx
pop rax
ret
; ***************************************************
; загрузка оверлейной функции
run:
mov r8, rbx
;int open(const char *path, int oflag, ... );
mov rax, 5 ;системмный вызов open
mov rcx, 0000000b
int 80h
;ssize_t read(int fildes, void *buf, size_t nbyte);
mov rbx, rax
mov rax, 3 ;системный вызов read
mov rcx, ostart
mov rdx, 10 ;размер буфера для записи оверлейной функции
;закрыываем файл
int 80h
mov rax, 6
int 80h
;вывод сооxбщения об успешном завершении операции
mov rdx, str_funloaded
call print
mov rdx, r8
call print
mov rdx, nline
call print
ret
; ***************************************************
main:
mov rdx, promt1
call print
push promt2
call puts
; обработка параметров командной строки
;mob rbx, o_sum
;call run
;выход из программы
exit:
mov rdx, str_exit
call print
mov rax, 1
mov rbx, 0
int 80h
error:
;print promt3
Ошибка сегментации, когда функция put вызывает функцию strrlen: Вот backtrace:
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7abc3a1 in __strlen_sse2 () from /lib/libc.so.6
(gdb) bt
#0 0x00007ffff7abc3a1 in __strlen_sse2 () from /lib/libc.so.6
#1 0x00007ffff7aa56ec in puts () from /lib/libc.so.6
#2 0x000000000040058a in main () at lab4_x64.asm:112
Еще такой вопрос к знатокам дела: В 64 битных процессорах отказались от сегментных регистров? Или как? Потому что, yasm при трансляции сообщил, что сегментные регистры игнорируются. Я понимаю, что в 32 битных их оставили для совместимости. Или я не так понял что-то?