2017-10-14 2 views
2

당신이 시스템 호출 번호 4를 사용하여 뭔가를 인쇄 할 수 있습니다인쇄 뭔가 리눅스에서

mov eax,4  ;system call number 
mov ebx,0  ;file descriptor 
mov ecx,msg  ;adress of message in data segment 
mov edx,length ;length of message 

그러나이 어떻게 스택 세그먼트에서 무언가를 인쇄 할 수 있습니까?

나는이 시도 :

push 'H' 
push 'e' 
push 'l' 
push 'l' 
push 'o' 
push ' ' 
push 'w' 
push 'o' 
push 'r' 
push 'l' 
push 'd' 
mov eax,4  ;system call number 
mov ebx,0  ;file descriptor 
mov ecx,ebp  ;adress of message 
mov edx,11  ;length of message 

을하지만 아무것도 인쇄되지 않습니다. 편집

: 나는 내 코드의 일부를 변경했고 지금은 이렇게이다 :

section .data 
msg: db "Hola mundo",0Ah 
ok: db "OK",0Ah 

section .text 
global _start 
_start: 
push 'leH' 
push 'w ol' 
push 'dlro' 
mov eax,4  ;system call number 
mov ebx,1  ;file descriptor 
mov ecx,esp  ;adress of message in data segment 
mov edx,11  ;length of message 
mov eax,1 
xor ebx,ebx  ;same as move ebx,0 but better 
int 0x80 

편집 2 (여전히 작동하지 않는)

section .data 
msg: db "Hello world",0Ah 

section .text 
global _start 
_start: 
push 'leH' 
push 'w ol' 
push 'dlro' 
mov eax,4  ;system call number 
mov ebx,1  ;file descriptor 
mov ecx,esp  ;adress of message in data segment 
mov edx,11  ;length of message 
int 0x80 
mov eax,1 
xor ebx,ebx  ;same as move ebx,0 but better 
int 0x80 

주석에 응답, 나는 조립 및 컴파일 :

nasm -f elf64 hello.asm && ld hello.o && ./a.out 

저는 우분투 64 비트 리눅스에서 일하고 있습니다.

+0

'ebp'는 스택 포인터가 아니며, 'esp'는입니다. 또한 'push'는 문자 당 4 바이트를 사용하므로 제대로 작동하지 않습니다. – Jester

+0

'push'를 사용하여 문자열을 뒤집을 필요는 없습니다. – Jester

+0

@Jester 문자열의 뒤집기는 내가 테스트하고 싶은 것입니다 –

답변

2

질문에 원래 중요한 정보가 부족했습니다. 조립 및 연결 대상 :

nasm -f elf64 hello.asm && ld hello.o && ./a.out 

이렇게하면 64 비트 실행 파일이 생성됩니다. int 0x80은 64 비트 실행 파일에서 사용하면 안됩니다. 64 비트 프로그램에서 스택 포인터는 32 비트 ESP 레지스터에서 나타낼 수 없습니다. 64 비트 포인터를 사용하는 유일한 방법은 syscall 명령어를 사용하는 것입니다. Ryan Chapman's blog에는 syscall 명령어를 통해 64 비트 시스템 호출 인터페이스 사용에 대한 유용한 정보가 있습니다.

section .text 
global _start 
_start: 
    mov dword [rsp-4], `rld\n` 
        ; Use back ticks instead of single quotes 
        ; To parse the string like C. We can write safely 
        ; in the 128 bytes below RSP because of the 
        ; Linux red zone. 
    mov dword [rsp-8], 'o Wo' 
    mov dword [rsp-12],'Hell' 
    mov eax,1  ;Write system call number 
    mov edi,eax  ;file descriptor (1 = stdout) 
    lea rsi,[rsp-12];address of message on the stack 
    mov edx,12  ;length of message 
    syscall 
    mov eax,60  ;Exit system call 
    xor edi,edi  ;RDI=0 
    syscall 

가 제로가 전체 64 비트 레지스터로 확장이기 때문에이 코드는 32 비트 레지스터에 상수를 기록 :

당신은 당신의 코드를 수정하는 경우

는 같이 보일 수있는 인터페이스를 준수합니다. 64 비트 즉시 값을 푸시 할 수는 없지만 문자열을 32 비트 DWORD 값으로 직접 스택에 쓸 수 있습니다. RSP을 조정할 필요가 없습니다. Linux에는 비동기 이벤트 및 신호에 의한 clobbered로부터 보호되는 128 바이트 red zone이 있기 때문입니다.

당신이 그것에 C 이스케이프 문자로 C 스타일의 문자열을 사용하려면

, NASM supports backtick 대신 작은 따옴표는 구분을합니다. 이렇게하면 새 줄 문자를 나타내는 문자로 \n과 같은 것을 사용할 수 있습니다. 이후에 삭제 된 질문에 게시 된 코드 중 일부에 개행 문자를 넣으려는 것으로 보입니다.

+1

코드 밀도의 경우 실제로 'push'와 'mov'를 섞을 수 있습니다. 'push 'Hell'' /'mov dword [rsp + 4],'Wo''. 보너스로 문자열 앞을 가리키는 rsp로 끝나기 때문에 'lea'대신 'mov'만 있으면됩니다. 또한 기계어에 리터럴 0 바이트가 없어도'execve'에 널 문자로 끝나는 문자열을 쉽게 얻을 수 있습니다. 그러나 이해하기가 훨씬 간단한 '좋은'푸쉬 (push)가 아닌 예를 +1하십시오! –