[2013-09-03 11:27] 研究实验1~研究实验5
研究实验1
minic文件夹里必须的文件:
tc.exe TCCONFIG.TC C0S.OBJ EMU.LIB MATHS.LIB GRAPHICS.LIB CS.LIB
研究实验2
main貌似可以看成一个汇编里的标号(offset),本人机器上main函数的开始地址为1fa。
研究实验3
(2)
main()
{
*(short far *)(0xb8000000+160*12+80)=0x0200+'a';
}
(3)
全局变量存储在向上生长的空间中,这个空间与局部变量共享一个段。
在一个函数内,局部变量存储在向下生长的空间中,BP>=SP,第一个局部变量的最后一个字节在SS:[BP-1]处,最后一个局部变量的第一个字节在SS:[SP]处,字SS:[BP]存储的是上一个函数的BP,字SS:[BP+2]存储的是上一个函数的返回地址;如果发生该函数调用子函数的情况,从字节SS:[SP-1]向下存储的是子程序的参数、返回地址和本函数BP。
函数开头执行push bp,是为了要将当前函数的父函数的BP保存;
mov bp,sp则改变当前环境,这时,当前函数的字SS:[BP]存储的是该函数的父函数的BP。
(4)
靠AX传递返回参数。
(5)
/* 可以将原来的程序改为如下形式 */
main()
{
char *Buffer = (char *)malloc(20);
*(int far *)0x02000000 = (int)Buffer;
Buffer[10]=0;
while(Buffer[10] != 8){
Buffer[Buffer[10]]='a'+Buffer[10];
Buffer[10]++;
}
}
研究实验4
(1)
链接环节会出错,因为缺少main函数,可能与C0S.obj文件有关。
(2)
偏移地址为0,无法正确返回,代码共29个字节。
(3)
能正确返回,代码共3783个字节,main函数与f函数没有区别。
(4)
对main函数进行调用的指令地址在偏移量为11a处;
整个程序返回指令int 21h在偏移量为156处。
(5)
对main函数调用和返回的指令从C0S.obj中来,在链接的过程中C0S.obj被链接进主程序。
(6)
这两个文件中的程序代码开始部分完全相同。
(7)
c0s.exe的11a处的指令为call 11d,m.exe的11a处的指令为call 1fa。
(9)
个人认为从内存保护的角度来说这个函数一点也不安全,因为它往以DS:0开始的这些不知道是否安全的位置写入了数据。
研究实验5
(1)
参数存储被调用者从右至左压栈,在子函数中,字SS:[BP+4]为最左边的参数,然后依据低地址到高地址的顺序记录从左至右的参数。
PS:字SS:[BP]为父函数的BP,字SS:[BP+2]为函数的返回地址。
(2)
showchar函数是在被调用时知道要显示哪些字符,其参数n确定显示的字符数。
(3)
/* 一个简陋的myPrintf */
#define VIDEO 0xb8000000
#define BLACK 0
#define WHITE 7
void cdecl __int__(int interruptnum);
void getCursor(int *x,int *y)
{
_AH = 3;
_BH = 0;
__int__(0x10);
*x = _DL;
*y = _DH;
}
void setCursor(int x,int y)
{
_AH = 2;
_BH = 0;
_DH = y;
_DL = x;
__int__(0x10);
}
void newLine()
{
int x,y;
getCursor(&x,&y);
y++;
x = 0;
setCursor(x,y);
}
void printChar(char c,int color)
{
int x,y;
getCursor(&x,&y);
*(short far *)(VIDEO + 160 * y + x * 2) = c | (color << 8);
if(x >= 80){
newLine();
}
else{
x++;
setCursor(x,y);
}
}
void space(int n)
{
int i;
for(i = 0;i != n;i++){
printChar(' ',BLACK);
}
}
void putChar(char c)
{
int color = WHITE;
switch(c){
case '\n':newLine();break;
case '\t':space(4);break;
default:printChar(c,color);
}
}
void putDigit(int n)
{
if(n > 0){
putDigit(n / 10);
putChar(n % 10 + '0');
}
else if(n < 0){
putChar('-');
putDigit(-n);
}
}
void myPrintf(char *fmt,...)
{
int pos,step,num;
step = 6;
for(pos = 0;fmt[pos];pos++){
if(fmt[pos] == '\\'){
pos++;
switch(fmt[pos]){
case 'n':putChar('\n');break;
case 't':putChar('\t');break;
case 0:return;
default:putChar(fmt[pos]);
}
}
else if(fmt[pos] == '%'){
pos++;
switch(fmt[pos]){
case 'c':
num = *(int *)(_BP + step);
putChar((char)num);
break;
case 'd':
if(num = *(int *)(_BP + step)){
putDigit(num);
}
else{
putChar('0');
}
step += 2;
break;
case 0:
return;
default:
putChar(fmt[pos]);
}
}
else{
putChar(fmt[pos]);
}
}
}
void main()
{
myPrintf("test:%d%c\n",-10,'h');]
myPrintf("he%d%d%d,w%dr%dd",1,1,0,0,1);
}
minic文件夹里必须的文件:
tc.exe TCCONFIG.TC C0S.OBJ EMU.LIB MATHS.LIB GRAPHICS.LIB CS.LIB
研究实验2
main貌似可以看成一个汇编里的标号(offset),本人机器上main函数的开始地址为1fa。
研究实验3
(2)
main()
{
*(short far *)(0xb8000000+160*12+80)=0x0200+'a';
}
(3)
全局变量存储在向上生长的空间中,这个空间与局部变量共享一个段。
在一个函数内,局部变量存储在向下生长的空间中,BP>=SP,第一个局部变量的最后一个字节在SS:[BP-1]处,最后一个局部变量的第一个字节在SS:[SP]处,字SS:[BP]存储的是上一个函数的BP,字SS:[BP+2]存储的是上一个函数的返回地址;如果发生该函数调用子函数的情况,从字节SS:[SP-1]向下存储的是子程序的参数、返回地址和本函数BP。
函数开头执行push bp,是为了要将当前函数的父函数的BP保存;
mov bp,sp则改变当前环境,这时,当前函数的字SS:[BP]存储的是该函数的父函数的BP。
(4)
靠AX传递返回参数。
(5)
/* 可以将原来的程序改为如下形式 */
main()
{
char *Buffer = (char *)malloc(20);
*(int far *)0x02000000 = (int)Buffer;
Buffer[10]=0;
while(Buffer[10] != 8){
Buffer[Buffer[10]]='a'+Buffer[10];
Buffer[10]++;
}
}
研究实验4
(1)
链接环节会出错,因为缺少main函数,可能与C0S.obj文件有关。
(2)
偏移地址为0,无法正确返回,代码共29个字节。
(3)
能正确返回,代码共3783个字节,main函数与f函数没有区别。
(4)
对main函数进行调用的指令地址在偏移量为11a处;
整个程序返回指令int 21h在偏移量为156处。
(5)
对main函数调用和返回的指令从C0S.obj中来,在链接的过程中C0S.obj被链接进主程序。
(6)
这两个文件中的程序代码开始部分完全相同。
(7)
c0s.exe的11a处的指令为call 11d,m.exe的11a处的指令为call 1fa。
(9)
个人认为从内存保护的角度来说这个函数一点也不安全,因为它往以DS:0开始的这些不知道是否安全的位置写入了数据。
研究实验5
(1)
参数存储被调用者从右至左压栈,在子函数中,字SS:[BP+4]为最左边的参数,然后依据低地址到高地址的顺序记录从左至右的参数。
PS:字SS:[BP]为父函数的BP,字SS:[BP+2]为函数的返回地址。
(2)
showchar函数是在被调用时知道要显示哪些字符,其参数n确定显示的字符数。
(3)
/* 一个简陋的myPrintf */
#define VIDEO 0xb8000000
#define BLACK 0
#define WHITE 7
void cdecl __int__(int interruptnum);
void getCursor(int *x,int *y)
{
_AH = 3;
_BH = 0;
__int__(0x10);
*x = _DL;
*y = _DH;
}
void setCursor(int x,int y)
{
_AH = 2;
_BH = 0;
_DH = y;
_DL = x;
__int__(0x10);
}
void newLine()
{
int x,y;
getCursor(&x,&y);
y++;
x = 0;
setCursor(x,y);
}
void printChar(char c,int color)
{
int x,y;
getCursor(&x,&y);
*(short far *)(VIDEO + 160 * y + x * 2) = c | (color << 8);
if(x >= 80){
newLine();
}
else{
x++;
setCursor(x,y);
}
}
void space(int n)
{
int i;
for(i = 0;i != n;i++){
printChar(' ',BLACK);
}
}
void putChar(char c)
{
int color = WHITE;
switch(c){
case '\n':newLine();break;
case '\t':space(4);break;
default:printChar(c,color);
}
}
void putDigit(int n)
{
if(n > 0){
putDigit(n / 10);
putChar(n % 10 + '0');
}
else if(n < 0){
putChar('-');
putDigit(-n);
}
}
void myPrintf(char *fmt,...)
{
int pos,step,num;
step = 6;
for(pos = 0;fmt[pos];pos++){
if(fmt[pos] == '\\'){
pos++;
switch(fmt[pos]){
case 'n':putChar('\n');break;
case 't':putChar('\t');break;
case 0:return;
default:putChar(fmt[pos]);
}
}
else if(fmt[pos] == '%'){
pos++;
switch(fmt[pos]){
case 'c':
num = *(int *)(_BP + step);
putChar((char)num);
break;
case 'd':
if(num = *(int *)(_BP + step)){
putDigit(num);
}
else{
putChar('0');
}
step += 2;
break;
case 0:
return;
default:
putChar(fmt[pos]);
}
}
else{
putChar(fmt[pos]);
}
}
}
void main()
{
myPrintf("test:%d%c\n",-10,'h');]
myPrintf("he%d%d%d,w%dr%dd",1,1,0,0,1);
}
评论次数(0) |
浏览次数(556) |
类型(汇编作业) |
收藏此文 |