2017-04-18 13 views
1

하나의 번호를 가져 와서 인쇄 한 어셈블리 프로그램을 만들려고했습니다. 하지만 1을 쓸 때 4171을 썼습니다. 왜, 어떻게 고칠 수 있습니까? 나는 64 비트 어셈블리를 사용하고 있는데, nasm -f macho64 scanf.asm으로 어셈블하고, gcc -o scanf scanf.o -Wl,-no-pie으로 연결했다. 그리고 스캔 매크로에서 숫자 주위에 대괄호 (대괄호 숫자에 대한 포인터)를 사용하려했지만 nasm mach-o는 그것을 허용하지 않으므로 그렇게하지 않았습니다.어셈블리 번호 변경 오류

; lib.asm 
extern _printf 
extern _scanf 

%macro print 2 

    push rbp 

    mov rdi, %1 
    mov rsi, %2 

    xor rax, rax 

    call _printf 

    pop rbp 

%endmacro 

%macro scan 2 

    push rbp 

    mov rdi, %1 
    mov rsi, %2 

    mov rax, 0 
    call _scanf 

    pop rbp 

%endmacro 

; scanf.asm 

%INCLUDE "lib.asm" 

section .bss 
    number resd 1 
section .text 
    global _main 
_main: 

    print str_out, qst 
    scan int_in, number 

    print ans, number 

exit: 

    mov rax, 0x2000001 
    xor rbx, rbx 
    syscall 

section .data 
    str_out db '%s', 0xa, 0 
    int_in db '%d', 0 
    int_out db '%d', 0xa, 0 


    qst db 'Enter a number: ', 0 

    ans db 'You wrote: %d', 0xa, 0 
+0

'print ans, number'는 숫자 자체가 아닌'number'의 주소를 인쇄하고있는 것 같습니다. 'print ans, number'를'movsx rax, dword [number]''print ans, rax'로 대체하면 어떨까요? 이 경우'mov eax, [number]''print ans, rax'도 제대로 작동합니다. –

+0

nasm은 "movsx rax, dword [number]"를 시도 할 때 "scanf.asm : 12 : error : Mach-O 64 비트 형식이 32 비트 절대 주소를 지원하지 않습니다"라는 메시지를 출력하고 "mov rax, 번호]". – SpilledMango

+0

이렇게'mov rax, [rel number]'상대 RIP 주소 지정을 사용하도록하십시오. –

답변

2

매크로 대답이 잘못 인쇄 :

여기 내 코드입니다. 매크로는 당신이 얻을 것 확장

print ans, number 

:

push rbp 

mov rdi, ans  ; RDI = Address of ans 
mov rsi, number ; RSI = Address of number 

xor rax, rax 

call _printf 

pop rbp 

나는 2 개 위 라인과 그 의미 댓글을 달았습니다. 'You wrote: %d'의 형식 문자열은 정수를 인쇄합니다. 대신 number의 주소를 전달했습니다. 이 문제를 해결하려면 number에서 32 비트 값을 가져 와서 사용 가능한 레지스터에 저장하고 해당 레지스터를 매크로에 전달하십시오. 이렇게하려면

당신은 대체 할 수

print ans, number 

으로 :

push rbp 

mov rdi, ans  ; RDI = Address of ans 
mov rsi, rax  ; RSI = number to print in RAX 

xor rax, rax 

call _printf 

pop rbp 

:로 확장 할

mov eax, [rel number] ; Get the 32-bit number from number and store in eax 
         ; Using RIP relative addressing 
print ans, rax  ; Print the 32-bit word in the bottom half of RAX. 

우리는 rel 지시어로 mov eax, [rel number]를 사용 기본 절대 주소를 변경하려면 RIP 상대 주소 지정 기능을 제공합니다. mov eax, [number]을 사용하고 rel을 지정하지 않으려면 기본 주소 지정을 무시하고 default rel을 어셈블리 파일의 맨 위에 놓을 수 있습니다. 기본값은 default abs입니다.


내가 제안 이유를 당신은 요청할 수 있습니다

:

mov eax, [rel number] ; Get the 32-bit number from number and store in eax 
         ; Using RIP relative addressing 
print ans, rax   ; Print the 32-bit word in the bottom half of RAX. 

을하는 대신 :

print ans, [rel number] 

궁극적으로 매크로이 할 시도했을 :

mov rsi, [rel number] ; Get the 64-bit number from number and store in RDI 

당신은 정의를 number this way :

number resd 1 

이것은 64 비트가 아닌 32 비트 값입니다. mov rsi, [rel number]은 메모리 위치 number에서 8 바이트를 RSI으로 이동하려고했습니다. 이 경우 샘플 코드에 문제가 발생하지 않지만 나쁜 형식으로 간주됩니다. 나는 그것이 작동 할지도 모른다는 사실에도 불구하고 버그라고 생각한다.

+0

그것은 효과가 있었지만, 장애물을 해결하기 위해 상단에 'DEFAULT REL'을 넣어야했습니다. – SpilledMango

+0

필자는 대답의 맨 아래에 코멘트를 달았지만 맨 위에 'default rel'이없는'mov eax, [rel number] '를 받아 들여야합니다. –