Two instructions control the use of assembly-language procedures. CALL pushes the return address onto the stack and transfers control to a procedure, and RET pops the return address off the stack and returns control to that location.
The CALL instruction pushes the address of the next instruction in your code onto the stack and passes control to a specified address. The syntax is:
CALL {label | register | memory}
The operand contains a value calculated at run time. Since that operand can be a register, direct memory operand, or indirect memory operand, you can write call tables similar to the example code on page 164.
call 니모닉은 함수(Procedure) 를 호출한다.
회귀 주소를 스택에 푸시한다.
함수로 제어권을 넘긴다.
call 니모닉의 피연산자중 “label”을 제외한 나머지 피연산자는 모두 실행 중에 실행할 함수가 결정된다.
“The operand contains a value calculated at run time.”라고 표현했다.
Near vs Far
MASM 6.1 Programmer's Guide, Ch.7 p.181 — "Near and Far Calls"
Calls can be near or far. Near calls push only the offset portion of the calling address and therefore must target a procedure within the same segment or group.
Near call 은 2바이트 오프셋을 스택에 푸시한다.
Far call 은 오프셋과 CS값(총 4바이트)을 스택에 푸시한다.
“The processor assumes all memory references are relative to the segment in the DS register, with the exception of references using BP or SP. The processor associates these registers with the SS register.”
mov di, [bx] ; Reads from DS:[bx]mov [di], cx ; Writes to DS:[di]mov [bp+6], ax ; Writes to SS:[bp+6]mov bx, [bp] ; Reads from SS:[bp]
[di]의 기본 세그먼트는 ds다. 따라서 ds:di로 최종 주소를 구하면 된다.
레지스터를 확인해보니 di의 값은 0000, ds의 값은 0C9E다.
TINY 모델이라 모든 세그먼트 레지스터의 값은 동일하다.
따라서 0C9E:0000에 덤프해서 확인해보자.
ds:di 에 저장된 값은 CD20임을 확인했다.
2바이트를 읽으면 된다. push 니모닉은 2바이트 워드 단위로 동작한다.
메모리 → 레지스터 → 메모리의 바이트 순서 보존 (little endian round trip)
push [di]에서 DS:0000의 값 CD 20이 스택에도 CD 20으로 보이는 이유:
DS:0000에서 워드 읽기 → 바이트 CD 20 → CPU 내부에서 20CDh(리틀 엔디언을 복원)
20CDh를 스택에 push → 리틀 엔디안 저장 → 바이트 CD 20
리틀 엔디안 → 레지스터 → 리틀 엔디안이라 메모리 덤프상 바이트 순서가 동일하게 보인다.
push [di]는 메모리 간접 피연산자
[] 와 di 레지스터를 사용했기 때문에 알 수 있다.
push fcount
push fcount 의 바이너리는 Code View에서 PUSH WORD PTR [0116]라고 표현한다.
어셈블 시점에서 변수 fcount의 주소를 안다.
mov dx, OFFSET fcount가 어셈블되어 Code View에서 MOV DX,0116라고 보여준다.
OFFSET Operator
Programmer's Guide, Chapter 3 — The OFFSET Operator (p.60)
An address constant is a special type of immediate operand that consists of an offset or segment value. The OFFSET operator returns the offset of a memory location.