I've been writing a C application, and I came in need of x86 assembly language. I'm pretty new to assembly, and the following snippet causes recursion:
unsigned int originalBP;
unsigned fAddress;
void f(unsigned short aa) {
printf("Function %d\n", aa);
}
unsigned short xx = 77;
void redirect() {
asm {
pop originalBP
mov fAddress, offset f
push word ptr xx
push fAddress
push originalBP
}
}
If i call redirect , it will repeatedly output: "Function 1135"
First, here are a few information about the environment in which this code is executed:
- This code is written to be executed under NTVDM
- Tiny memory model is used ( all segment pointer registers point to the same segment )
Here's my expectation of what the code above should do ( this is most likely the culprit of the error ) :
- Pop the stack and store value in
originalBP; I believe the value is actually the address of the current function i.e.redirect - Push
f's argument value ( value ofxx) to the stack - Push address of
fto stack ( since there's only one segment, only offset is needed ) - Push back the address of
redirect
Of course, if this were the correct flow, recursion would be apparent ( except the part where 1135 is printed instead of 7). But interestingly, doing the same with a function with no arguments produces only one line of output i.e.:
unsigned int originalBP;
unsigned fAddress;
void f() {
printf("Function");
}
void redirect() {
asm {
pop originalBP
mov fAddress, offset f
push fAddress
push originalBP
}
}
This probably means that my understanding of the above code is completely wrong. What is the real issue in this code?
EDIT: I probably left some of the things unsaid:
- This is a 16 bit application
- Compiler used is Borland C++ 3.1, as Eclipse plugin
redirectis called frommainasredirect()
EDIT (regarding Margaret Bloom's answer) Here's an example of instruction execution once redirect is called. Values in brackets represent stack pointer register and the value at that location before each instruction is executed:
- call redirect
- (FFF4-04E6)
push bp - (FFF2-FFF6)
mov bp, sp - (FFF2-FFF6)
mov fAddress, offest f - (FFF2-FFF6)
pop originalBP - (FFF4-04E6)
pop originalRIP - (FFF6-0000)
push xx(I've changed xx to 1187) - (FFF4-0755)
push originalRIP - (FFF2-04E6)
push fAddress - (FFF0-04AC)
push originalBP - (FFEE-FFF6)
pop bp - (FFF0-04AC)
ret- (in f) (FFF2-04E6)
push bp - (FFF0-FFF6)
mov bp,sp - printf executes
- (FFF0-FFF6)
pop bp - (FFF2-04E6)
retNext statements seems to bereturn 0;which is the end of main.
- (in f) (FFF2-04E6)
Execution continues trough bunch of lines, and somehow comes back to the line calling redirect.