NASM 어셈블러를 배우고 있으며 라인 피드를 처리하는 중 순간에 고생하고 있습니다.NASM의 스택에 PUSH 된 줄 바꿈을 인쇄 할 수 없습니다
어떻게 줄 바꿈을 인쇄합니까? 내가 보여줄거야. 중 하나를 사용할 수있는
sprint:
push rdx
push rbx
push rax
push rcx
mov rax, rcx
pop rcx
jmp next_char
ret
sprint_syscall:
mov rbx, 1
mov rax, 4
int 80h
pop rax
pop rbx
pop rdx
ret
sprint_linefeed:
call sprint
push rcx
mov rcx, 0Ah
push rcx
mov rcx, rsp
call sprint
pop rcx
pop rcx
ret
next_char:
cmp byte [rax], 0
jz count_length
inc rax
jmp next_char
count_length:
sub rax, rcx
mov rdx, rax
jmp sprint_syscall
quit:
push rbx
push rax
mov rbx, 0
mov rax, 1
int 80h
pop rax
pop rbx
ret
메인 응용 프로그램 : 나는 학습을 위해 준비했습니다
$ uname -a
Linux 4.4.0-97-generiC#120-Ubuntu SMP Tue Sep 19 17:28:18 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
$ lsb_release -a
No LSB modules are available.
Distributor ID : Ubuntu
Description : Ubuntu 16.04.3 LTS
Release : 16.04
Codename : xenial
내 기능 : 나는 그것을 보여하지만 그 전에, 내 플랫폼에 대해 얘기하는 것이 중요합니다 주어진 기능 :
%include 'functions.asm'
SECTION .data
msgFirst db "Hello World!", 0h
msgSecond db "Another string.", 0h
SECTION .text
global _start
_start:
mov rcx, msgFirst
call sprint_linefeed
mov rcx, msgSecond
call sprint_linefeed
call quit
모두 잘 컴파일되고 작동합니다. 와/링크를 컴파일 할 경우에도 불구하고, 당신이 볼 수 있듯이
Hello World!Another string
이 어떤 라인 피드이되지 않은 :
nasm -g -f elf64 -l main.lst main.asm -o main.o && ld main.o -o main
을 그리고 컴파일 된 응용 프로그램을 실행, 우리가 볼 수있어
sprint_linefeed:
call sprint
push rcx ; push rcx onto the stack to preserve it
mov rcx, 0Ah ; move 0Ah into rcx, 0Ah is the ASCII char for a linefeed
push rcx ; push the linefeed char onto the stack
mov rcx, rsp ; move the address of the pointer into rcx for the 'sys_write' syscall
call sprint
pop rcx ; remove the linefeed char from the stack
pop rcx ; restore the original value of rcx
ret
그래서, 내 행동의 설명은을 참조 : 줄 바꿈을 인쇄하기 위해 다음 지침을 사용하는 sprint_linefeed
함수를 호출에주어진 문자열을 호출 한 다음 0Ah
문자를 스택으로 푸시합니다. 나중에 sprint()
함수를 다시 호출하기 위해 RSP 레지스터에서 포인터를 가져옵니다. syscall이 주어진 문자열 (http://fresh.flatassembler.net/lscr/data/004.html)을 인쇄하기 위해 포인터를 필요로하기 때문에 완료되었습니다.
SECTION .data
msgFirst db "Hello World!", 0Ah, 0h
이 같은 함수를 호출하지만, sprint_linefeed()
정의 되었기 때문에 다른 문자열 값으로, 우리에게 기다려온 결과를 제공하지만, 그것은 아무 의미 :
경우 문자열 선언에 OAh
문자를 추가합니다 여분의 ASCII-char의 선언을 전달합니다.
sprint_linefeed()
이 잘 작동하려면 소스 코드에서 무엇을 수정해야합니까?
64 비트 코드에서 'int 80h'을 사용하지 마십시오. 32 비트 호환성 시스템 호출 인터페이스입니다. [64 비트 코드에서 32 비트 int 0x80 Linux ABI를 사용하면 어떻게됩니까?] (https://stackoverflow.com/questions/46087730/what-happens-if-you-use-the-32-bit) -int-0x80-linux-abi-in-64-bit-code) – Jester
@Jester 조언을 주셔서 감사합니다. – Neverlands
'rsp'는 32b 경계를 넘을 가능성이 매우 높으므로'int 0x80'은 스택 메모리에서'0A' 문자열을 읽지 못합니다.'strace'를 사용하여 시스템 호출이 무엇을 반환하는지 확인해보기를 권합니다. 그러나 64b 바이너리의'int 0x80'도 실제로 혼란 스러울 것입니다. 그래서 출력은 그다지 중요하지 않습니다. asm을 32b로 다시 작성하고 elf32로 컴파일하거나 시스템 호출을 수정하십시오. – Ped7g