2012-10-27 2 views
3

ecx의 값이 0 인 후에 프로그램을 끝내고 싶을 때 왜 내 프로그램이 무한 루프에 빠지는 지 알 수는 없습니까? 도와주세요?조립! 루프를 종료 할 수 없습니까?

section .data 
;get external functions 
extern printf 
global main 
main: 

;set up stack frame 
push rbp 
mov rbp, rsp 

;if(x<y) 
;print x is less 
;else 
;print y is larger than x 

;mov values into register to compare them 
mov rax,[x] 
mov rbx,[y] 
cmp rax,rbx ;cmp x,y 
jg .x_is_greater 
lea rdi,[y_less] 
xor eax,eax ;must clear eax when using printf 
call printf 
jmp .done 

.x_is_greater: 
;print "X is greater to the screen" 

;mov r11,[count] 
;lea rdi,[x_greater] 
;xor eax,eax 
;call printf 
;mov r12,[zero] 
;cmp r11,r12 
;jg .myloop ;jump to myloop if greater than zero 
;jmp .done ;return if equal to 0 
mov ecx, 3; [count] 
;mov r12, [zero] 
jmp .myloop 
.myloop: 
;;dec r11 
;dec rcx 
lea rdi,[fmt] 
lea rsi,[ecx] 
;mov rdx,[r12] 
xor eax,eax ;must clear eax when using printf 
call printf 

cmp ecx, 0 
jz .done 
lea rdi,[x_greater] 
xor eax,eax ;must clear eax when using printf 
call printf 
lea rdi,[fmt] 
lea rsi,[ecx] 
;mov rdx,[r12] 
xor eax,eax ;must clear eax when using printf 
call printf 
dec ecx 

;sub rcx,[one] 
jmp .myloop 
;jmp .done 
.done: 
leave 
;xor eax, eax 
ret;exit program 

;leave ;destroy stack frame 

section .bss 

section .data 
prompt db "This is a practice program to test what I know!",0x0a,0 
y_less db "Y < X",0x0a,0 
x_greater db "X > Y ",0x0a,0 
x db 10 
y db 1 
count dq 3 
zero db 0 
one dq 1 
fmt db "R11 %d ",0x0a,0 

답변

1

Printf를 호출하십시오. EBX에 번호를 추가했습니다. 그것은 poping, pushing, stacking없이 작동합니다 :). 일부 사람들에게 도움이되기를 바랍니다.

extrn ExitProcess: PROC 
extrn printf: PROC 

.data 
fmt db '%s',10,0 ; The printf format, "\n", '0' 
check db 'HALO',0 

.code 
Start PROC 

xor eax,eax 
mov rbx,1 

start_while: 
    cmp rbx,10 
    jge end_while 

    lea rcx,check 
    lea rdx,fmt 
    call printf 


    add rbx,1 
    jmp start_while 
end_while: 
xor eax,eax 
xor rbx,rbx 
call ExitProcess 
Start ENDP 
End 
5

함수를 호출 할 때 (예를 들어, printf)는, 당신이 속한 "

http://www.x86-64.org/documentation/abi.pdf

레지스터 %의 RBP %의 RBX 및 % R12 %의 R15을 통해 ecx

의 가치를 보존 할 필요가 "을 호출 함수에 전달하고 호출 된 함수는 값을 보존해야합니다. 즉 호출 된 함수는 호출자에 대해이 레지스터의 값을 으로 보존해야합니다. 나머지 레지스터는 호출 된 기능에 속합니다. 호출하는 함수가 함수 호출을 통해 그러한 레지스터 값을 보존하려면 해당 값을 로컬 스택 프레임에 저장해야합니다.

1

printf 호출은 ecx 레지스터의 값을 변경시킬 수 있습니다. 그래서 당신은 다음 중 한 가지해야 할 일 :

  • printf 호출하기 전에 스택에 푸시를하고 pop 그것의 printf 호출 후에을;
  • 피 호출자 저장 레지스터를 루프 카운터로 사용하십시오. 또는
  • callee-saved 레지스터에 저장하고 복원합니다. 첫 번째 옵션의

예 : 나는 printf와 함께 루프라는 WHILE-DO를 만든 그냥 RAX는 RCX는, RDX는, R9, R8이 사용하는 마이크로 소프트 비주얼 스튜디오에 체크 한

.myloop: 
lea rdi,[fmt] 
lea rsi,[ecx] 
xor eax,eax ;must clear eax when using printf 
push ecx ; saved 
call printf 
pop ecx ; restored 

cmp ecx, 0 
jz .done 
lea rdi,[x_greater] 

push ecx ; saved 
xor eax,eax ;must clear eax when using printf 
call printf 
pop ecx ; restored 

lea rdi,[fmt] 
lea rsi,[ecx] 

push ecx ; saved 
xor eax,eax ;must clear eax when using printf 
call printf 
push ecx ; restored 

dec ecx 
jmp .myloop 
+1

"이 작업을 수행 할 필요가 없습니다"... 64 비트 (사용중인 일부 레지스터를 기반으로하는 경우) 인 경우 ** 할 수 있습니다 ** 다양한 인수를 허용하는 함수를 호출 할 때'eax'를 지울 필요가 있습니다. 20 페이지의 각주 # 13을 참고하십시오. [http://www.x86-64.org/documentation/abi.pdf] (http://www.x86-64.org/documentation/abi.pdf). 또한 50.7 페이지에서 시작하는 3.5.7 절에 대한 추가 토론이 있습니다. – cbranch

+0

+1은 알지 못했습니다. BTW는 그가'rax' 전체를 정리해야만하는 것 같습니다. –

+1

기술적으로, 나는 단지 낮은 바이트 ('al') 만 실제로 사용된다고 생각하지만, 개인적으로는 가독성을 위해서'rax' 전체를 정리할 것입니다. – cbranch