C语言中处理结构体的原理
汇编中有几种寻址方式,分别是直接寻址:(ds:[idata])、寄存器间接寻址(ds:[bx])、寄存器相对寻址(ds:[bx + idata]、ds:[bx + si])基址变址寻址(ds:[bx + si])、相对基址变址寻址([bx + si + idata])。
结构体的存储逻辑图如下:(以下数据表示某公司的名称、CEO、CEO的福布斯排行、收入、代表产品)
现在假设公司的CEO在富豪榜上的排名为38,收入增加了70,代表产品变为VAX,通过汇编编程修改上述信息,以下是相应的汇编代码:(假设数据段为seg)
mov ax,seg
mov ds,ax
mov bx,0
mov word ptr ds:[bx + 12],38
add [bx + 14],70
mov si,0
mov byte ptr [bx + 10 + si],'V'
inc si
mov byte ptr [bx + 10 + si],'A'
inc si
mov byte ptr [bx + 10 + si],'X'
对应的C语言代码可以写成:
struct company
{
char cn[3];
char name[9];
int pm;
int salary;
char product[3];
};
company dec = {"DEC","Ken Olsen",137,40,"PDP"};
int main()
{
int i;
dec.pm = 38;
dec.salary += 70;
dec.product[i] = 'V';
++i;
dec.product[i] = 'A';
++i;
dec.product[i] = 'X';
return 0;
}
对比C语言代码和汇编代码,可以看出,对于结构体变量,系统会先根据定义分配相应大小的空间,并将各个变量名与内存关联起来,结构体对象名与系统分配的空间的首地址相对应(定义的结构体对象的首地址在段中的相对地址存储在bx中),即在使用dec名时实际与汇编代码“mov ax,seg” “mov ds,ax”
对应,将数据段段首地址存入ds寄存器中,系统根据对象中的变量名找到对应的偏移地址,偏移地址的大小由对应的数据类型决定,如cn数组前没有变量,cn的偏移地址为0,cn所在的地址为 ds:[bx],cn为长度为3的字符型数组,在上一个偏移地址的基础上加上上一个变量所占空间的大小即为下一个变量的偏移地址,所以name数组的首地址为ds:[bx + 3],这样给出了对象名就相当于给定了该对象在段中的相对地址(上述代码中的bx),给定了对象中的成员变量名就相当于给定了某一内存在对象中的偏移地址(ds:[bx + idata])。根据数组名可以找到数组的首地址,但数组中具体元素的访问则需要给定元素个数,即si的值来定位数组中的具体内存,C语言中的 ++i 相当于汇编中的 (add si ,数组中元素的长度)。
根据以上的分析可以看出,构建一个结构体对象时,系统会在代码段中根据结构体的定义开辟相应大小的内存空间,并将该空间在段中的偏移地址与对象名绑定。对象中的变量名与该变量在对象所在内存中的偏移地址相关联,数组中的标号用于定位数组中的元素在数组中的相对位置。(对象名决定bx,变量名决定bx + idata,数组中的元素标号决定bx + idata + si)。
C语言中处理结构体的原理的更多相关文章
- C语言中的结构体,结构体数组
C语言中的结构体是一个小难点,下面我们详细来讲一下:至于什么是结构体,结构体为什么会产生,我就不说了,原因很简单,但是要注意到是结构体也是连续存储的,但要注意的是结构体里面类型各异,所以必然会产生内存 ...
- Verilog缺少一个复合数据类型,如C语言中的结构体
https://mp.weixin.qq.com/s/_9UsgUQv-MfLe8nS938cfQ Verilog中的数据类型(Data Type)是分散的,缺少一个复合数据类型:把多个wire, r ...
- C语言中的结构体和C++中的结构体以及C++中类的区别
c++中结构体可以定义一个函数 C中的结构体和C++中结构体的不同之处:在C中的结构体只能自定义数据类型,结构体中不允许有函数,而C++中的结构体可以加入成员函数. C++中的结构体和类的异同: 一. ...
- C语言中的结构体
用户自己建立自己的结构体类型 1. 定义和使用结构体变量 (1).结构体的定义 C语言允许用户自己建立由不同类型数据组成的组合型的数据结构,它称为结构体. (2).声明一个结构体类型的一般形式为: ...
- c语言中的结构体指针类型的cast
1.我们在c语言中会经常碰到强制类型转换. 在这,我介绍一种结构pointer类型转换,但是有前提(有点类似于c++中的继承中的子父对象的cast). 简单的介绍一下: 首先我们要知道一个结构的指针, ...
- 018_go语言中的结构体
代码演示 package main import "fmt" type person struct { name string age int } func main() { fm ...
- Go语言中的结构体 (struct)
Golang官方称Go语言的语法相对Java语言而言要简洁很多,但是简洁背后也灵活了很多,所以很多看似很简单的代码上的细节稍不注意就会产生坑.本文主要对struct结构体的相关的语法进行总结和说明. ...
- C语言中全局结构体指针隐含的错误
前天在嵌入式系统上,调试一个数组的全局变量时,发现该变量一直会动态变化.深入分析, 才发现该全局结构体没有申请内存,而是用了一个指针.这种情况编译器是检查不出来的,在linux 上运行会挂掉,但是在裸 ...
- C语言中的结构体是怎么定义的_怎么使用?
结构体的定义 // 定义结构体st struct st{ int a; // 成员a int b; // 成员b }; #include <stdio.h> struct st{ int ...
随机推荐
- Bootstrap入门Demo——制作路径导航栏
今天在在群里聊天的时候看到一仅仅程序猿发了一张用Bootstrap做的界面.感觉挺好看.然后去官网看了下组件.发现都挺美丽的,然后看到了路径导航栏,刚好要做这个东西,然后就下了Bootstrap的源代 ...
- Express4.x API (一):application (译)
Express4.x API 译文 系列文章 Express4.x API (一):application (译) -- 完成 Express4.x API (二):request (译) -- 完成 ...
- F02 金融学第二定律 资金的积聚
美国南北战争,北方取胜的关键在于发行了债券,从而积聚了资金,提升了北方军队战斗力. 纽约的逆袭,得益于伊利运河的修建,而伊利运河的建造需要的资金,全靠债券发行积聚的资金. 聚积起来的资金,往往决定了重 ...
- 自学WPF之Binding(一)
Binding的重要性就不作介绍了,是作为数据交互的支撑,下面来介绍一下为Binding指定源(Source)的几种方法: 把普通CLR类型的单个对象指定为Source:包括.NET Framewor ...
- RESTful 的通俗解释
转载自知乎,通俗易懂的讲解了RESTful链接:https://www.zhihu.com/question/28557115/answer/48094438 REST -- REpresentati ...
- Targets选项下Other linker flags的设置
-ObjC:加了这个参数后,链接器就会把静态库中所有的Objective-C类和分类都加载到最后的可执行文件中 -all_load:会让链接器把所有找到的目标文件都加载到可执行文件中,但是千万不要随便 ...
- Base64转换二进制文件对象 Blob/Base64转换 File 对象
function convertBase64UrlToBlob(urlData) { var arr = dataurl.split(','),//去掉url的头,并转换为byte type = ar ...
- iOS框架搭建(MVC,自定义TabBar)--微博搭建为例
项目搭建 1.新建一个微博的项目,去掉屏幕旋转 2.设置屏幕方向-->只有竖向 3.使用代码构建UI,不使用storyboard 4.配置图标AppIcon和LaunchImage 将微博资料的 ...
- JS如何实现导航栏的智能浮动
<script language="javascript"> function smartFloat(obj) { var obj = docu ...
- ES6 let和const命令(4)
const声明的常量只在当前代码块有效.如果想设置跨模块的常量,可以采用下面的写法. //constants.js模块 export const A = 1; export const B = 3; ...