2017-01-06 2 views
0

jmp를 호출하여 액세스하는 코드의 일부로 여전히 어셈블리의 주요 기능의 일부로 간주됩니까?메인 함수의 일부로 간주되는 글로벌 메인에서 어셈블리가 튀어 나오고 있습니까?

예 :

main: 
    mov ebx,3 
    push ebx 
    jmp for_loop ; this part 
rec: 
    ;some function 
for_loop: 
    ;logic 
    je exit 
    call rec 
    ;logic 
    jmp for_loop 
exit: 
    pop ebx 
    mov eax,0 
    ret 

JMP를 사용하고 main에서 for_loop을 쓸 수있는 더 좋은 연습이 될 것인가?

답변

1

글쎄, 엉망진창 같아.

조립시 주요 기능이 없습니다. 실행이 시작되는 "main"이라고하는 엔트리 포인트를 호출 할 수도 있지만, 실제로 그 것입니다. 그것은 단지 기계 코드에 존재하지 않는 상상의 레이블 일뿐입니다. 함수는 call이 될 것입니다. 왜냐하면 프로세서의 call 명령어가 jmp 일 때 몇 가지 설정을 수행하기 때문입니다.하지만 그게 전부입니다.

개인적으로, 나는 이것을 상당히 재구성 할 것입니다.

main: 
    xor ebx,ebx 
    add ebx,3   ; saves a byte 
    push ebx 
forloop: 
    ; I assume here you do a dec, or cmp, for the following: 
    je exit 
    ; put the code for "rec" in here. 
    ; No point wasting the bytes and time to jump. 
    jmp forloop 
exit: 
    pop ebx 
    xor eax,eax 
    ret 

좋아요, 그래도 여전히 엉망입니다. 그러나 당신이 달성하고자하는 것에 대해 내 지식에는 공백이 있습니다.

처음에는 je exit이 그 전에가는 "논리"에 연결됩니다. 나는 개인적으로 이것을 해소하려고 노력할 것입니다. 즉, "논리"로 가정하면, 나는 이것을 jne forloop으로 바꾸고 루프의 끝 부분에 놓을 것이다. 그래서 jmp를 처음부터 피할 수있다. 또한 몇 바이트를 다시 저장합니다.

xor eax,eax은 레지스터를 0으로 설정하는 짧고 빠른 방법입니다. 실제로 rec이 별도의 기능을 필요로하는 경우 적어도이 블록 외부에 놓으므로 jmp for_loop을 사용하여 건너 뛸 필요가 없습니다. ret 이후에 안전하게 넣을 수 있습니다.

+0

'jne forloop'에'jne exit'을 편집했는데, 그렇지 않으면 작동하지 않을 것이기 때문입니다. –

+0

'xor' +'add''가 "바이트를 저장"하는 것을 어떻게 생각합니까? 그것은 2 + 3 바이트이며, 반면에 'mov ebx, 3'은 * 역시 * 5 바이트입니다. 같은. 단일 명령을 선호하십시오. –

+0

errr, 물론 맞습니다. 나는'xor'가 더 짧아 져서'add '가 그것을 평준화한다는 것을 무시했다. –

1

전체 부분 :

rec: 
    ; some function (ending with ret?!) 

코드의 exit: 부분에있는 ret 후 이동 될 수는, 당신은 다음과 같이, "REC"별도로 "기본"함께, 그리고됩니다

main: 
    ; some init 
    ; some loop doing "call rec" 
    ; something something 
    ret 

rec: 
    ; some "function" code 
    ret 

그럼 다시, 일부 "기능"내부 소스의 또는 여부 지침의 논리 그룹이 무엇인지 전혀, 어떤 방법으로 인식하지의 CPU에 문제가되지 않으며, "얼마나 깊은" .

CPU는 cs:eip 주소 포인터를 가져 와서 + 다음 명령을 실행합니다. 그것이 실행의 특정 순간에 알 수있는 전부입니다.

jmp 명령은 eip을 다른 주소로로드 한 후 다음에 명령을 실행합니다.

"서브 루틴"메커니즘은 반환 주소를 ret 명령어로 eip에 다시로드하는 스택 메모리에 저장하는 방식으로 작동하지만 유효하지 않은 반송 주소 나 다른 주소를 포함하도록 다른 방법으로 스택 내용을 조정하면 ret이 충돌하거나 다른 주소로 "점프"하게되면 CPU는 일부 서브 루틴의 내부에 있다는 것을 알지 못하며 CPU에서 "복귀"할 필요가 없습니다. 이 모든 것은 프로그래머가 작성한 고급 의미 논리로서, 실행 경로를 올바르게 디자인하고 "서브 루틴 호출"또는 "메인 루프"와 같은 논리적 패턴을 형성해야합니다.

CPU에는 cs:eip과 다른 레지스터의 내용과 메모리 내용 만 있습니다. 어떤 상태가 명령 실행에 앞서 가는지는 결정적으로 어떤 명령이 다음에 실행되고 어떤 영향을 미칠지 결정 론적으로 결정합니다. CPU 레지스터 및 컴퓨터 메모리 (및 I/O 버스 또는 특정 "매핑 된"I/O 제어 메커니즘). 당신이 소스를 읽 그래서


는 쉽게/야윈 소스를 쓰기에 더 많은 시간을 투자하는 것을 주저하지 않는, 인간에 의해 쉽게 "읽기"에 대한 소스를 작성, 주변의 다른 방법으로 그것을 넣어 여러 번 (디버깅, 수정)보다 WRITING 이상입니다. 그래서 당신의 예제에서는 코드의 "rec"부분을 "main code"의 main-loop-ret 체인을 인터리브하지 않고 이동시키는 것이 훨씬 더 합리적입니다. 원본 수준에서 더 잘 읽어야합니다.

어셈블리에서 주 기능의 일부로 간주되는 jmp를 호출하여 액세스하는 코드의 일부입니까?

출처의 독자에 따라, 그녀가 주된 부분인지 아닌지 여부에 달려 있습니다. 기계는 이러한 명령 그룹 개념을 신경 쓰지도 않고 이해하지도 않습니다.

관련 문제