b2科目四模拟试题多少题驾考考爆了怎么补救
b2科目四模拟试题多少题 驾考考爆了怎么补救

从汇编的角度来看,C语言标识符以及为什么数组名的地址与数组名的值相同

电脑杂谈  发布时间:2020-07-15 04:18:35  来源:网络整理

c语言嵌入汇编_c语言对应汇编语句_c语言与汇编语言的区别

我以前一直有一个问题,为什么数组名的地址和数组名的值相同. 简单地听别人谈论这个事情实际上很难理解. 我认为从编译的角度理解这个问题很容易.

int main()
{
    int a = 1;
    int c[10] = {1,2,3,4,5,6};
    return 0;
}

一段简单的代码,让我们从汇编的角度来看它. 首先要说明的是,c语言中的标识符(即变量的名称)实际上没有地址空间,也就是说,他实际上并不占用空间,但是他所代表的值却占用了空间. 为什么称它为标识符,因为它只是一个标识符,所以等同于一个地址,该地址的值就是该标识符表示的地址.

以上面的a为例,我们绘制图片以了解

上面的a = 0xff1122并不是说a的值等于0xff1122,而是a的标识符等同于该地址值,他是一个替代物,需要理解. 然后,我们对与程序集对应的变量a的访问等效于

c语言与汇编语言的区别_c语言嵌入汇编_c语言对应汇编语句

MOV AL,[ff1122H]

是将存储在地址ff1122中的值传输到AL寄存器,因此标识符a实际上是一个辅助函数,它代表一个地址.

mov指令的功能是取出保存在[]中地址值位置的值.

请注意,实际上有汇编语言中的变量名. 为了避免这个问题,我们继续进行散发. 我们对其进行了简化,并尝试从机器的角度看问题.

您不能让我为您编写机器代码.

CPU运行时,无法理解变量名是什么. 对他而言,一条指令中只能有操作数,并且操作数具有不同的类型.

c语言嵌入汇编_c语言对应汇编语句_c语言与汇编语言的区别

8086/8088指令系统中有三种主要类型的操作数: 立即操作数(即常量),寄存器操作数(例如通用寄存器AX,段寄存器DS)和内存操作数(存储在内存中)数据. )

因此,我们编写的变量名称不在编译后生成的机器代码中.

了解这些知识之后,您实际上可以了解上述标识符的替代效果.

基于上述基础,让我们理解为什么数组名和数组名采用相同的地址值.

我们还将数组名称视为标识符. 它也代表一个地址,但是该地址不同于先前的地址. 地址也是一种. 实际上,它不能称为地址. 实际上有地址的类型. 它是一个值,其类型取决于操作他的指令. 操作他的指令从该地址读回一些位,以表示该地址值表示的类型. 因此,所有标识符实际上代表一个公共地址值,但是该值的操作指令不同,显示的类型也不同.

返回数组名称c语言对应汇编语句,该数组名称实际上表示该数组的第一个地址值,但是我们用于地址值的命令与上面由a表示的用于地址值的命令不同,它显示的结果不同的.

c语言与汇编语言的区别_c语言对应汇编语句_c语言嵌入汇编

我们上面提到的a标识符等效于0xff1122,因此我们在程序中采用标识符a的地址,实际上,它为您提供了由a标识符表示的地址.

直接读取a的值时,它会读取标识符a所表示的地址所指向的值,然后根据不同的操作指令(不同的操作指令确定该指令要处理多长时间),从该地址开始读取不同的数字.

看一段代码: 然后我们使用GCC生成汇编代码c语言对应汇编语句,以查看汇编如何处理该程序

int a = 1;
int c[10] = {1,2,3,4,5,6};
printf("%d",a);
printf("%d",&a);
printf("%d",c);
printf("%d",&c);

生成的汇编代码,数字8和9的行无所谓,它代表以下汇编语言用c语言表示的哪一行,这只是对codeBlock的相应处理,以帮助我们控制代码.

;8  :	    printf("%d",a);
0x4013d2	mov    0x3c(%esp),%eax
0x4013d6	mov    %eax,0x4(%esp)
0x4013da	movl   $0x408024,(%esp)
0x4013e1	call   0x401350 <printf>
;9  :	    printf("%d",&a);
0x4013e6	lea    0x3c(%esp),%eax
0x4013ea	mov    %eax,0x4(%esp)
0x4013ee	movl   $0x408024,(%esp)
0x4013f5	call   0x401350 <printf>
;10 :	    printf("%d",c);
0x4013fa	lea    0x14(%esp),%eax
0x4013fe	mov    %eax,0x4(%esp)
0x401402	movl   $0x408024,(%esp)
0x401409	call   0x401350 <printf>
;11 :	    printf("%d",&c);
0x40140e	lea    0x14(%esp),%eax
0x401412	mov    %eax,0x4(%esp)
0x401416	movl   $0x408024,(%esp)
0x40141d	call   0x401350 <printf>

c语言嵌入汇编_c语言对应汇编语句_c语言与汇编语言的区别

esp是一个指针寄存器,其内部值指向堆栈的顶部. 0x3c是偏移地址,最终的操作地址是esp + 0x3c.

lea可以将有效地址传输到指定的寄存器,即,将上述esp + 0x3c地址值传输到指定的寄存器.

mov 0x3c(%esp),%eax表示将栈顶偏移量0x3c的值保存到%eax寄存器中,我们可以看到,当直接输出a时,它是标识符a在代表处存储的值地址位置已输出.

lea 0x3c(%esp),%eax表示将a标识符表示的地址的偏移值保存在%eax寄存器中,即将a表示的地址保存在%eax寄存器中,然后输出,最终输出是变量a的地址.

然后看一下数组c的以下操作,我们发现当我们直接输出a时,它也是lea指令,为什么,因为不能直接输出c标识符表示的地址位置的值,所以如何输出数组存在语义错误,但它可以帮助我们进行转换,即直接输出c表示的地址值.

&c很容易理解. C最初表示此数组,然后将数组的地址偏移量放入%eax寄存器中. 然后进行输出.

看一段代码,我们直接输出c [0]来查看程序集的样子

;12 :	    printf("%d",c[0]);
0x401422	mov    0x14(%esp),%eax
0x401426	mov    %eax,0x4(%esp)
0x40142a	movl   $0x408024,(%esp)
0x401431	call   0x401350 <printf>

我看到了. 这次我用mov代替了上面的lea. mov只是采用esp + 0x14地址指向的值并将其放入%eax寄存器中.


本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-280776-1.html

    相关阅读
      发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

      热点图片
      拼命载入中...