对一段C函数的分析

王爽《汇编语言》
第四版 p326
研究实验5.2
void showchar(int, int, …);
main()
{
showchar(8, 2, ‘a’, ‘b’, ‘c’, ‘d’, ‘e’, ‘f’, ‘g’, ‘h’);
}
void showchar(int n, int color, …)
{
int a;
for(a = 0; a!= n; a++)
{
*(char far *)(0xb8000000+160*10+80+a+a) = *(int *)(_BP+8+a+a);
*(char far *)(0xb8000000+160*10+81+a+a) = color;
}
}
//
在debug中,
main开始的位置为:
CS:IP=0B3C:01FA
mian函数的结构为:
(ADD:01FA)
PUSH BP
MOV SP,BP
POP BP
RET
然后,把8,2,’a’, ‘b’, ‘c’, ‘d’, ‘e’, ‘f’, ‘g’, ‘h’这几个数,按照逆序依次输入AX,并PUSH到栈中。
然后,CALL 022D,即进入showchar程序中。
进入showchar之后,函数结构为:
(ADD:022D)
PUSH BP
MOV BP,SP
PUSH SI
XOR SI,SI
JMP 027E
(ADD:0235)
(ADD:027E)
CMP SI,[BP+04]
JNZ 0235
POP SI
POP BP
RET
此处结构一个是BP入栈,一个是SI入栈,SI相当于C语言中的int a变量。
在ADD:027E处,CMP SI,[BP+04],相当于C语言中的(a != n),
此处BP + 04 = FFD4, [FFD4] = 08, [FFD5] = 00, [FFD4 FFD5] = 00 08,
即[BP+04] = 0008,这个值就是C语言中showchar函数中的 int n 的值,即8.
SI => int a;
[BP+04] => int n;
CMP SI,[BP+04] => for(a = 0; a != n; a++)中的if a != n 这一部分。
就是说,如果SI == 8,那么就结束该子程序, RET回去到main函数中。
如果SI != 8,那么就 JNZ 0235。
从0235到027E,该处是一处循环,用SI从0开始计数,每次+1,一直到SI == 8,结束循环,RET出去。
这一段程序,做两个事情,
一个是把位于SS:FFD0 + 8 + SI + SI 中的一个字节的数据取出来,PUSH 到SS:FFCC中。
当SI == 0 的时候,SS:FFD0 + 8 + SI + SI == SS:FFD8, 其中的数据为’a’,
然后再从SS:FFCC中取出来,送到B800:160*10+80+SI+SI中去。
第二件事是把SS:FFD0 + 6 中的一个字节的数据取出来,PUSH 到SS:FFCC中。
当SI == 0 的时候,SS:FFD0 +6 == SS:FFD6, 其中的数据为2,即C语言中showchar函数的int color。
然后再从SS:FFCC中取出来,送到B800:160*10+81+SI+SI中去,为上一个字节中的数据填色。
然后SI+1,接着就到了27E:CMP SI,[BP+04],进入下一轮循环,一直到SI == 8为之。
通过这个程序可以看出,在mian函数中的变量是存在mian函数BP之后的栈中的。
而进入showchar函数之后,编辑器并没有给该函数中的变量一个固定的栈空间。
8作为循环次数存在了main的栈中;
而‘a’这些字符以及2这个颜色是在每次循环中,重复送入到showchar函数内的固定的SS:FFCC这个栈空间内,
下一个循环还在这里,尽管上一个循环的数据已经被覆盖。
栈中情况如下表所示:
其中,蓝色的为栈地址,纵轴+横轴即为具体地址,如FFE0+5=FFE5。
绿字为该地址下的18位数据,黑字为注释。
一个小格代表一个字节,栈中的数据为16bit的字数据,因此每两小格为一个16bit字作为注释格。
0 1 2 3 4 5 6 7 8 9 A B C D E F
FFE0 65 00 66 00 67 00 68 00 F4 FF 1D 01 01 00 F2 FF
‘e’ ‘f’ ‘g’ ‘h’ IP=01FB
PUSH BP
IP=01FA
SP=FFEA
FFD0 E8 FF 28 02 08 00 02 00 61 00 62 00 63 00 64 00
PUSH BP
SP=BP=FFD0
SP=FFD2,保存main的IP=0228 int n = 8 int color=2 ‘a’ ‘b’ ‘c’ ‘d’
FFC0 00 00 00 00 61 00 5A 03
循环中,计算使用 循环中,计算使用 每个循环该空间一次存字符,一次存颜色 PUSH SI
SI => int a
滚动至顶部