C语言基础知识汇编分析

1.静态、动态存储变量的区别 C语言源码: fun() {        int i = 0x100;        static int c = 0x200;        i = c; } 汇编代码: push       bp mov bp, sp push       si mov si, 100h       ;定义动态变量 i = 0x100 mov si, ds:[00
摘要由CSDN通过智能技术生成

       1.静态、动态存储变量的区别

C语言源码:

fun()

{

       int i = 0x100;

       static int c = 0x200;

       i = c;

}

汇编代码:

push       bp

mov bp, sp

push       si

mov si, 100h       ;定义动态变量 i = 0x100

mov si, ds:[0000] ;对静态变量赋值i = c;ds:[0000]内存储的是静态变量C

pop si

pop bp

retn

       总结: 其实静态变量类似于全局变量,实现方式类似。


2.在C语言中将数组做为参数传递给函数
2009-08-04 08:42

C语言源码:

void change(int[]);

fun()

{

       int a[] = {1,2};

       add(a);

}

void change(int a[])

{

       int tmp;

       tmp=a[0];

       a[0]=a[1];

       a[1]=tmp;

}

汇编代码:

push       bp

mov bp, sp

sub sp, 4     ;开辟堆栈空间,保存数组数据

push       ss

lea   ax, [bp-4]

push       ax         ;es:di压栈

mov ax,0

push       ax

push       ds        ;ds:si压栈

mov cx,4       ;设置数组数据所占字节数,即需复制字节数

call sub_100C7

lea   ax, [bp-4]   ;此命令就是将数组的首地址传给调用的函数

push       ax         ;将数组的首地址压栈传递给子程序change

call sub_100C6

pop cx        ;平衡堆栈

mov sp, bp

pop bp

retn

sub_100C6:     ;change函数

push       bp

mov bp, sp

push       si

push       di        ;tmp局部变量

mov si, [bp+4]   ;将数组首地址读入si寄存器

mov di, [si]      ;si保存的是一个地址,这个地址中存储就是a[0],即指针 tmp = a[0]

mov ax, [si+2]   ;ax = a[1]

mov [si], ax     ;a[0]=ax a[0]=a[1] 通过ax寄存器中转

mov [si+2],di   ;a[1]=tmp

pop di

pop si

pop bp

retn

sub_100C7:     ;复制数据段数组数据至开辟的堆栈空间中            

push       bp

mov bp, sp

push       si

push       di

push       ds

lds   si, [bp+6]

les   di, [bp+0Ah]

cld

shr   cx, 1

rep movsw

adc cx, cx

rep movsb

pop ds

pop di

pop si

pop bp

retf 8

总结:传递数组其实就是传递数组的首地址,可以理解为传递的是数组指针,对数组的操作,将会影响数组中的数据。


3.语言的函数

这个的内容比较多,有点重量级。呵呵。。       

C语言源码:

int add(int,int);

fun()

{

       int a = 0x10;

       int b = 0x100;

       int c = add(a,b);

}

int add(int a,int b)

{

       int c;

       c = a + b;

       return c;

}

汇编程序代码:

push       bp

mov bp, sp     压栈bpbp寄存器将在后续部分作为基址寄存器使用

sub sp, 2      在堆栈中分配空间给变量C

push       si

push       di

mov si, 10h    变量a=0x10

mov di, 100h   变量b=0x100

push       di       

push       si        压栈ba做为参数传递给add函数

call sub_100B0

pop cx      

pop cx       平衡堆栈,pop cx机器指令较短,执行效率高,相当于add sp,4

mov [bp-2], ax 将返回值付给变量CC语言中通过ax寄存器返回函数值

pop di

pop si

mov sp, bp

pop bp

retn          至此函数fun返回

sub_100B0:

push       bp

mov bp, sp

push       si       

mov si, [bp+4] c = a

add si, [bp+6] c = a + b

mov ax, si     将结果传给ax寄存器

pop si

pop bp

retn        add子程序返回

总结:函数进入时基本上都有push bpmov bp,sp语句,此两条语句将bp寄存器压栈,过后做为基址寄存器使用。

调用函数时,先将参数从右到左依次压栈,执行call指令时,将ip压栈,接着将bp压栈,所以在16位的CPU中,取参数时,bp+4取得第一个参数,bp+6取得第二个参数,依次类推。局部变量使用使用sub sp,2指令在堆栈中开辟空间存储,所以取局部变量时,通过bp-2取得第一个局部变量,bp-4取得第二个局部变量,函数若有返回值一般通过ax寄存器返回。最后要执行mov sp,bppop bp指令平衡局部变量占用的堆栈空间,实际的参数并未清空。Ret后弹出ip值,返回调用程序执行的地址。

一般情况下由调用函数的程序平衡堆栈,所以上例pop cx执行两次,相当于add sp,4平衡堆栈。但数组中传送字符串的函数使用了ret n,由子程序本身进行了平衡堆栈的工作。

从上可以看到,在调用函数时,调用参数并未在子函数中更改,即在子函数中使用了参数值,但并未真正更改参数的值。使用指针做为参数时的情况,后续再研究。



4.数组的定义使用

C语言程序:

int x[] = {1,2};

int i = x[0]+x[1];

汇编程序代码:

Push bp

mov bp, sp

sub sp, 6          用到三个局部变量,其中数组2个,所以分配6个字节的堆栈空间

push       ss

lea   ax, [bp-6]

push ax

push       ds

mov ax, 194h

push       ax        以上压栈操作给子程序传递参数

mov cx, 4         数组占用字节长度

call SCOPY@ 注意:此处为远调用,压入CSIP寄存器

mov ax, [bp-6] ax寄存器内容x[1]

add ax, [bp-4]    x[0]+x[1]

mov [bp-2], ax    将结果付给[bp-2],即变量i

mov sp, bp

pop bp

retn                    以上语句为返回子程序

子程序SCOPY@

push bp

mov bp, sp

push si

push di

push ds               保存子程序中用到的寄存器

lds   si, [bp+6]    ds:si为调用程序中的DSAx的值,初始化字符串复制源地址

les   di, [bp+0Ah]es:di为堆栈空间的地址

cld

shr   cx, 1

rep movsw           将数据段中定义的数组内容复制到堆栈中分配的空间

adc cx, cx

rep movsb            此处有疑问,不太清楚。

pop ds

pop di

pop si

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值