스택 오버 플로우와 같은 커뮤니티에 액세스 할 수있는 컴퓨터 프로그래밍 기술을 배우는 데는 모두 다행 스럽습니다! 나는 컴퓨터를 프로그래밍하는 법을 배우는 일을 맡기로 결정했다. 그리고 나는 'Programming From the Ground Up'이라는 전자 책에 대한 지식으로 독자들에게 어셈블리 언어로 프로그램을 만드는 법을 가르치고있다. GNU/Linux 환경에서.모든 레지스터 이름을 eXX에서 rXX로 변경하여 32에서 64 비트로 이식하면 팩토리얼이 0을 반환합니까?
GCC의 어셈블러로 인한 오류없이 실행 한 함수를 사용하여 정수 4의 계승을 계산하는 프로그램을 만들었습니다. 프로그램. 그러나, 내 프로그램의 함수는 올바른 대답을 반환하지 않습니다! 4의 계승은 24이지만 프로그램은 0의 값을 반환합니다! 맞습니다. 왜 그런지 모르겠습니다.
.section .data
.section .text
.globl _start
.globl factorial
_start:
push $4 #this is the function argument
call factorial #the function is called
add $4, %rsp #the stack is restored to its original
#state before the function was called
mov %rax, %rbx #this instruction will move the result
#computed by the function into the rbx
#register and will serve as the return
#value
mov $1, %rax #1 must be placed inside this register for
#the exit system call
int $0x80 #exit interrupt
.type factorial, @function #defines the code below as being a function
factorial: #function label
push %rbp #saves the base-pointer
mov %rsp, %rbp #moves the stack-pointer into the base-
#pointer register so that data in the stack
#can be referenced as indexes of the base-
#pointer
mov $1, %rax #the rax register will contain the product
#of the factorial
mov 8(%rbp), %rcx #moves the function argument into %rcx
start_loop: #the process loop begins
cmp $1, %rcx #this is the exit condition for the loop
je loop_exit #if the value in %rcx reaches 1, exit loop
imul %rcx, %rax #multiply the current integer of the
#factorial by the value stored in %rax
dec %rcx #reduce the factorial integer by 1
jmp start_loop #unconditional jump to the start of loop
loop_exit: #the loop exit begins
mov %rbp, %rsp #restore the stack-pointer
pop %rbp #remove the saved base-pointer from stack
ret #return
** 컴퓨터 프로그래밍의 기술을 배우는 여러분 모두 ** 디버거 **에 액세스하는 것이 얼마나 행운입니까? 따라서 코드를 사용하여 코드가 잘못되는 부분을 찾으십시오. 힌트 : 이미 인수에 액세스하지 못했습니다. 추신 : x86-64 규칙은 인수 전달에 스택을 사용하지 않지만 올바르게 수행하면 스택을 사용할 수 있습니다. PPS : 64 비트 코드에서'int 0x80'을 사용하지 마십시오. 그것은 여기에서 일하는 것을 일어난다. – Jester
코드에 몇 가지 설명을 추가 할 수 있습니까? 프로그램이 기대하는 논거는 무엇입니까? - [book] (http://mirror.cedia.org.ec/nongnu/pgubook/ProgrammingGroundUp-1-0-booksize.pdf)의 사례는 모든 레지스터 대신 레지스터의 일부를 사용합니다 (예 : % rsp 대신 esp. - Github에서 반복적이고 재귀적인 [요인 구현] (https://github.com/bbyars/programming-from-the-ground-up/tree/master/ch4-functions)을 확인할 수 있습니다. . – Jaime
@Jaime 책의 예제는 x86 32b 어셈블리를위한 것입니다. 예를 들어, OP가 64b 변형과 레지스터 이름을 바꿔 가며 순진한 방식으로 x86-64로 변환하려고 한 것처럼 보입니다. 그래서 분명히 그 코드는 잘못된 모드로 실행되기 때문에 올바르게 작동 할 기회가 없습니다. OP : 책을 제대로 따라 가십시오. 64 바이트 리눅스에서 32 비트 바이너리를 컴파일하고 디버깅하는 방법을 찾아라. – Ped7g