研究试验5
程序员文章站
2022-06-07 09:38:53
...
研究试验5
函数如何接受不确定参数
编写a.c
,解答 相关问题
main
是如何给showchar
传递参数的?showchar
是如何接受参数?
a.c
-
c 代码
void showchar(char a, int b); main() { showchar('a', 2); } void showchar(char a, int b) { *(char far *)(0xb8000000 + 160 * 10 + 2 * 40) = 'a'; *(char far *)(0xb8000000 + 160 * 10 + 2 * 40 + 1) = 2; }
-
汇编代码
问题解答
-
main
函数通过 栈 给showchar
传递参数 -
showchar
应该也是从栈中获取的但是汇编代码中没有相关的栈操作。
编写 b.c
思考相关问题
showchar
函数是要如何知道呀显示多少个字符的?printf
函数是如何知道有多少个参数的?
b.c
-
c 代码
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; } }
-
汇编代码
printf
函数是如何知道有多少给参数
-
先写一个
printf.c
的测试用例main(){ printf("%c,%c,%c,%c",'a','b','c','d'); printf("%d,%d,%d,%d",1,2,3,4); }
-
汇编代码
-
第一个
printf
-
第二个
printf
-
通过对照
printf
函数 可以猜想mov ax,0194;
和mov ax 01a0
因该是printf
的第一个参数,然后通过debug
可以验证猜想是正确的通过观察可以看到
25 63 2c 25 63 2c 25 63 2c 25 63 2c 25 63 00
对应 字符串%c,%c,%c,%c
和25 64 2c 25 64 2c 25 64 2c 25 64 00
对应字符串%d,%d,%d,%d
,,故根据以往编程经验猜想00
为终止条件。所以把第三个%c
对应的汇编代码开头改变为00
,看看是不是只输出两个字符 通过下图可以看出猜想正确。所以可以得出printf
可能是根据传入的%
的个数来确定打印的字符数,读入一个%
就会读取后面一个字符来确定打印的方式,当读出一个0
时打印结束
-
问题解答
- 第一个参数
n
就是告知函数showchar
显示多少给字符 -
printf
是通过%
的个数来得知有多少个参数,通过00
来判断结束。
实现一个简单的 printf
函数 只需支持 %c,%d
即可
void myPrintf(char *, ...);
main()
{
myPrintf("xxxxx%c,%n,ddddd%d", 'x', 5);
}
void myPrintf(char *str, ...)
{
int stackIndex = 0;
int stringIndex = 0;
int screenIndex = 0;
int screenBenchmark = 160 * 10;
while (str[stringIndex] != 0)
{
if (str[stringIndex] == '%')
{
if (str[stringIndex + 1] == 'c')
{
*(char far *)(0xb8000000 + screenBenchmark + screenIndex) = *(char *)(_BP + 6 + stackIndex); /*跨 push call 第一个参数 才能取到相应的值*/
*(char far *)(0xb8000000 + screenBenchmark + screenIndex + 1) = 2;
screenIndex += 2;
stringIndex += 2;
stackIndex += 2;
}
else if (str[stringIndex + 1] == 'd')
{
*(char far *)(0xb8000000 + screenBenchmark + screenIndex) = *(char *)(_BP + 6 + stackIndex) + 0x30;
*(char far *)(0xb8000000 + screenBenchmark + screenIndex + 1) = 2;
stackIndex += 2;
screenIndex += 2;
stringIndex += 2;
}
else if (str[stringIndex + 1] == 'n')
{
screenBenchmark += 160;
screenIndex = 0;
stringIndex += 2;
}
}
else
{
*(char far *)(0xb8000000 + screenBenchmark + screenIndex) = str[stringIndex];
*(char far *)(0xb8000000 + screenBenchmark + screenIndex + 1) = 2;
screenIndex += 2;
stringIndex += 1;
}
}
}
上一篇: 汇编语言学习(六)课程设计一
下一篇: BigDecimalUtils