王爽《汇编语言》
第四版 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 BPMOV SP,BP…POP BPRET
然后,把8,2,’a’, ‘b’, ‘c’, ‘d’, ‘e’, ‘f’, ‘g’, ‘h’这几个数,按照逆序依次输入AX,并PUSH到栈中。
然后,CALL 022D,即进入showchar程序中。
进入showchar之后,函数结构为:
(ADD:022D)PUSH BPMOV BP,SPPUSH SIXOR SI,SIJMP 027E(ADD:0235)…(ADD:027E)CMP SI,[BP+04]JNZ 0235POP SIPOP BPRET
此处结构一个是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 |