Я пытаюсь изучить ассемблер (Intel x86 с NASM на Linux), и неудивительно, что у меня возникли некоторые проблемы.
Следующее предназначено для того, чтобы взять буфер текста, удалить все пробелы и поместить результат в другой буфер. Это часть более крупного проекта, который я делаю как способ обучения, и сначала я разрабатываю каждую часть отдельно. В реальном проекте сообщение будет приходить из файла, здесь я просто использую жестко закодированную строку (Msg
) для целей тестирования.
Но это не работает. Некоторое время я возился с этим, но уверен, что где-то пропустил фундаментальную концепцию или что-то в этом роде.
[SECTION .data]
Msg db ' %d Whitespace, thanks ', 10, 0
[SECTION .bss]
BUFFSIZE equ 80
BufferA resb BUFFSIZE
BufferB resb BUFFSIZE
[SECTION .text]
extern printf
global main
; PROCEDURE stripwhite
; INPUT None
; OUTPUT None
; NOTES Strips all leading and trailing whitespace from BufferA
; Result is stored in BufferB
stripwhite:
pushad ; Save caller's registers
mov eax, BufferA ; Source string
mov ebx, BufferB ; Output string
.loop:
mov cl, byte [eax] ; Get a single character from the source
cmp cl, 0
je .end ; End if character is null
cmp cl, 32
jne .save ; Save it if it's not a space
add eax, 1 ; Otherwhise skip to next character
jmp .loop
.save:
mov byte [ebx], cl ; Save character in output buffer
add eax, 1 ; Move on to next character
add ebx, 1
jmp .loop
.end:
mov byte [ebx], 0 ; Add a null at the end
popad ; Restore caller's registers
ret
main:
push ebp ; Set up stack frame for debugger
mov ebp, esp
push ebx ; Must preserve ebp, ebx, esi and edi
push esi
push edi
; start
mov dword [BufferA], Msg
call stripwhite
push 0
push BufferB ; Push message string
call printf ; Print line count
add esp, 8 ; Clean up the stack
; end
pop edi ; Restore saved registers
pop esi
pop ebx
mov esp, ebp ; Destroy stack frame
pop ebp
ret
Мне интересно, почему мне нужно использовать dword
в строке перед call stripwhite
выше, когда оба Msg
и два буфера используют байты, но компоновщик (в данном случае вызываемый GCC) выбрасывает ошибка, когда я использую что-либо еще:
stripwhite.o:stripwhite.asm:82: relocation truncated to fit: R_386_8 against `.data'
collect2: ld returned 1 exit status
Может быть, это как-то связано с этим, но я не могу понять, что.
Кажется, что следующее работает просто отлично, и оно в основном идентично, за исключением того, что код не находится внутри процедуры.
[SECTION .data]
Msg db ' %d Whitespace, thanks ', 10, 0
[SECTION .bss]
BUFFSIZE equ 80
BufferA resb BUFFSIZE
BufferB resb BUFFSIZE
[SECTION .text]
extern printf
global main
main:
push ebp ; Set up stack frame for debugger
mov ebp, esp
push ebx ; Must preserve ebp, ebx, esi and edi
push esi
push edi
; start
mov eax, Msg
mov ebx, BufferB
.loop:
mov cl, byte [eax]
cmp cl, 0
je .end
cmp cl, 32
jne .save
add eax, 1
jmp .loop
.save:
mov byte [ebx], cl
add eax, 1
add ebx, 1
jmp .loop
.end:
mov byte [ebx], 0
push 0
push BufferB ; Push message string
call printf ; Print line count
add esp, 8 ; Clean up the stack
; end
pop edi ; Restore saved registers
pop esi
pop ebx
mov esp, ebp ; Destroy stack frame
pop ebp
ret