2013-12-12 4 views
0

작은 프로그램을 x86-64 어셈블리 (AT & T) 구문으로 작성했으며 올바르게 어셈블했지만 예상 한 결과를 얻지 못합니다. 서브 루틴을 수정해야하는 레지스터 %rdi에 변수가 있습니다. 나중에 다른 용도로 사용하기 위해 원래 값을 유지해야합니다. 내가 원하는 것은 push에 스택에 원래의 값을 넣고 서브 루틴이 끝나면 다시 검색합니다. 예를 들어, 변수가 %rdi 인 경우입니다.변수를 스택에 저장 (X86-64 어셈블리)

pushq %rdi 
    call subroutine 
    movq (%rsp), %rdi 

지금이 올바른 방법인지 잘 모르겠습니다. 서브 루틴이 반환 값을 스택에 푸시한다고 읽었지만 변수를 검색하려고 할 때 오프셋을 포함해야한다는 의미입니까?

또한 스택 포인터를 16 바이트로 정렬해야한다는 것을 알고 있습니다. 그렇지 않으면 어셈블러가 내게 오류를 주겠습니까, 아니면 내 프로그램이 실패하는 이유가 될 수 있습니까?

그리고이 프로그램은 과제의 일부이므로 코드를 공유 할 수는 없지만 내 설명이 충분하기를 바랍니다.

+0

코드를 공유 할 수없는 과제에 대한 비밀이 무엇인지 상상할 수 없습니다. – Artur

+0

그것은 어떤 방식 으로든 비밀은 아니지만, 전체 프로그램을 웹 사이트에 게시하고 누군가 다른 사람에게 모든 실수를 바로 잡으라고 요청하면, 나는 부정 행위를 직면하게됩니다. – user680881

답변

0

코드 조각은 호출 시퀀스에서 스택 포인터 균형을 유지하는 데 실패한다는 점에서 의심 스럽습니다. 이는 의도 한 동작이 아닐 수 있습니다. 일반적으로 pushpop 연산을 여러 번 일치시키고 push을 여러 번 일치시킨 다음 addq $k, %rsp (여기서 k은 이전의 모든 결합 된 크기입니다) 또는 함수의 실행에서 프레임 크기를 일정하게 유지하고 명시 적 액세스를 사용합니다.

스택 포인터를 16 바이트 정렬로 유지해야 할 경우 일정 크기의 프레임을 유지하는 것이 가장 간단한 방법 일 수 있습니다. 그것은

# in the function prologue 
subq $K, %rsp 
... 
mov %rdi, SLOT(%rsp) 
call subroutine 
mov SLOT(%rsp), %rdi 
... 
# in the epilogue 
addq $K, %rsp 
, 16로 반올림 K 모든 지역 스택 상태 플러스 나가는 인수의 가장 큰 세트에 대한 충분한 공간을위한 충분한 공간이다

SLOT처럼 보일 수 있습니다하면 값에 예약 된 스택에 장소입니다 %rdi입니다.

정수 유형의 반환 값은 일반적으로 스택이 아닌 rax에 있습니다. 숨겨진 포인터와 같이 다른 형식이 다르게 반환됩니다. 인터페이스 할 컴파일러의 호출 규칙을 확인하십시오.

+0

좋아요, 그럼 내가 대답 할 수있는 것에 따라 다음 코드가 그걸 할 것입니까? subq $ 16, % RSP movq % RDI, 8 (%의 RSP) movq 8 (%의 RSP) 호출 서브 루틴, % RDI addq $ 16 %의 RSP – user680881

+0

미안 내 코드는 조금 읽을 수 없습니다. 희망은 괜찮습니다 – user680881

+0

저에게는 괜찮은 것처럼 보입니다. 보통 서브 루틴 호출마다 하나가 아닌 전체 함수에 대해 하나의'subq/addq' 쌍을 갖습니다. – gsg

0

movq (%rsp),%rdi 대신 popq %rdi을 사용하십시오. 첫 번째는 RSP 스택 포인터를 업데이트하지 않으므로 호출 한 함수로 돌아갈 때 문제가 될 수 있습니다.

물론이 경우 subroutine은 스택을 자체 조정하지 않습니다. subroutinestandard (Pascal) calling convention을 사용하고 있으며 매개 변수는 호출자가 아닌 함수 자체에서 제거되므로 저장된 %rdi 값에 대한 액세스가 느슨합니다.