그래서 NASM 구문 (오 신, 다시는이 아니라고 생각합니다.)을 사용하는 x86 Linux 어셈블리를 배우고 있습니다. 단순히 표준 출력 EAX 값을 인쇄하는 서브 루틴을 만들려고 해요. 코드가 실행되고 오류없이 종료되지만 아무 것도 인쇄되지 않습니다. 나는 이유를 알 수 없다. (I 과감한 뭔가를보고 싶어하지 않는 한이 아마 무관하다)이이 모양 내 주요 파일에서Linux x86 NASM - 서브 루틴 : EAX에서 dword 인쇄
segment .bss
to_print: resd 1
segment .text
global print_eax_val
print_eax_val: ; (top)
push dword ebx ;Stack: edx
push dword ecx ; ecx
push dword edx ; ebx
; (bot)
mov ecx,eax ;ecx = eax
mov [to_print],ecx ;to_print = ecx
mov eax, 4 ;sys_write
mov ebx, 1 ;to stdout
add ecx, 47 ;add 47 for ASCII numbers
mov edx, 2 ;double word = 2 bytes
int 0x80
mov eax, [to_print] ;eax = original val
pop edx ;pop the registers back from the stack
pop ecx
pop ebx ;Stack: empty
ret
라고 : 우선, 나는 여기에서 일하고 있어요 파일입니다.
segment .data
hello db "Hello world!", 0
newline db 0xA
len equ $ - hello
len2 equ $ - newline
segment .text
extern print_nl
extern print_eax_val
global main
main:
enter 0,0
call print_nl
mov eax, 1
call print_eax_val
mov ebx, 0 ;exit code = 0 (normal)
mov eax, 1 ;exit command
int 0x80 ;ask kernel to quit
print_nl
정의하고 개행 문자를 인쇄 또 다른 서브 루틴입니다. 이 성공적으로 실행되고 예상대로 새 줄을 인쇄합니다.
문제가 내 sys_write
호출의 길이 매개 변수와 관련이 있습니까? 저는 dword
의 크기 인 2를주고 있습니다. EAX
레지스터와 to_print
레이블의 크기는 resd 1
으로 예약되어 있습니다. 나는 절망에서 1, 4, 8, 16, 32로 길이를 바꿨다. 아무 것도 효과가 없었다.
편집 : (내가 변화 라인에 별표를 둘 것이다) : 궁금해 사람들을위한, 여기에 내가 코드를 고정하는 방법이다 기본적으로
segment .bss
to_print: resd 1
segment .text
global print_eax_val
print_eax_val: ; (top)
push dword ebx ;Stack: edx
push dword ecx ; ecx
push dword edx ; ebx
; (bot)
mov ecx,eax ;ecx = eax
mov [to_print],ecx ;to_print = ecx
**** add dword [to_print], 48
mov eax, 4 ;sys_write
mov ebx, 1 ;to stdout
**** mov ecx, to_print
mov edx, 2
int 0x80
**** sub dword [to_print], 48
mov eax, [to_print] ;eax = original val
pop edx ;pop the registers back from the stack
pop ecx
pop ebx ;Stack: empty
ret
는 ecx
가 주소를 포함해야합니다 인쇄하고자하는 블록의 값 자체가 아닌. 선택한 답변에서 지적한대로만 0-9 범위에있는 경우 작동합니다.
EDIT 2 : sys_write (edx
에 저장된 것)의 두 번째 매개 변수에 대해 약간 혼란 스러웠습니다. 나는 그것이 단지 많은 바이트를 참조한다고 생각한다. 따라서 dword
의 경우, 사용하고있는 것처럼 4를 사용하는 것이 적절합니다. 이중 단어는 4 바이트 또는 32 비트이기 때문입니다. 나는 x86이 리틀 엔디안이기 때문에 그것이 작동했다고 생각합니다.
90 00 00 00
을 그리고 둘의 공급 길이, sys_write와는 가져옵니다 : 그래서 메모리에, to_print
의 16 진수 값이 같을 것이다
90 00
그래서 값이 운이 좋게하지 않습니다 타락하다. 나는 위의 to_print
에게 값을 제공하지 않을거야 알고 있기 때문에
는 나중에, 바이트 여기 괜찮 ... resb 1
을 사용하고 dword
대신 byte
를 사용하여 액세스하는 대신 바이트로 to_print
를 저장하는 코드를 변경 9.
대단히 감사합니다. 당신의 대답은 매우 도움이되었습니다. 예, 이것이 0에서 9까지만 작동한다는 것을 알았습니다. 기본 사항 중 일부를 보려고합니다. 어쩌면 배열/포인터 int-to-string 비즈니스로 시작하겠습니다. 내가 알고 싶은 사람을 위해 업데이트 된 코드로 내 게시물을 수정합니다. –
어셈블리 언어에 대해 박수를 보냅니다. BTW, 귀하의 질문은 프로토 타입 좋은 질문입니다. 당신은 필요한 정보를 정확히주고, 당신이 시도한 것을 보여 주었고, 특정한 질문을했습니다. +1 –
다시 한 번 감사드립니다. 나는 답을 "프로토 타입 좋은 결과"로 분류 할 것입니다. 거대한 C++ segfault/포인터 붕괴 이후에 내가 작업중인 프로젝트에서 일부 x86 어셈블리를 배우기로 결정했습니다. 우선, 좋은 전환기입니다. 둘째, 실제로 코드를 작성할 때 어떤 일을하는지 알고 싶습니다. –