汇编与C语言一

本文介绍了汇编语言的起源,计算机的减法运算,8086系统的物理地址表示方法,以及存储器的演进。详细讲解了8086如何用两个寄存器表示物理地址,并探讨了C语言结构体在汇编层面的表示。
摘要由CSDN通过智能技术生成

一、汇编语言产生的原因
机器只能识别01序列串,以前程序员在写代码时,写的都是0101011101010这些鬼东西,不方便人类理解,美国人希望用英语单词来代替01序列串,为此他们创建了一张表,将可能用到的所有英文符号全部与01序列串对应,也就是说让人类写代码时写的是英文单词,编译的时候,用一个机器把英文单词编译成01序列串,机器就可以拿着01序列串开心地运行了,这个实现英文单词转成01序列串的机器就是汇编器,他们创建的那张表就是ASCII表;
由于需要表示的英文符号(包括abc之类的英文单词在内)大约有128个,一开始可能因为27=128,所以就让一个个的英文符号对应一个个的7位二进制数,但是考虑到扩展性,也就是说保不齐哪天想往这张表里再加几个字符,所以就需要让一个个英文符号与一个个8位二进制数对应,也就是说,表示一个符号,需要一个8位二进制数,这解释了为什么一个字节为8bit;

二、计算机的减法
计算机的加法非常简单,两个01串按二进制加就完事了,但是减法是需要被设计的,下面讲推出减法的心路历程(我也不知道是不是这么回事):
1.首先,用符号位的方式来区分正负数,1(10)= 0000 0001(2),所以 -1(10)= 1000 0001(2)

2.如果就这样让这两个二进制数相加的话,结果等于 1000 0010(2) = -2(10),得不到正确结果;

3.原码是将十进制数转为二进制数得到的码,反码就是将原码的符号位不变,剩余位取反,
比如 -1的反码就是将1000 0001变成 1111 1110,但是如果直接拿反码做减法的话,

				 1的原码是 0000 0001-1的原码是1000 0001,反码是 1111 11101的原码加-1的反码是 1111 1111;
         对其结果进行反码得 1000 0000

结果是-0,产生了逻辑错误(??),所以不能用反码来减(??);

4.补码就是将反码加一,-1的反码1111 1110,补一下变成1111 1111,让它与1的原码0000 0001相加,得到10000 0000,符号位溢出,变成了全0;

三、8086系统的物理地址表示方法

1.8086有三种总线:控制总线、数据总线和地址总线,一个个寄存器可以看做一个小区里的一栋栋楼房。我在我家给女朋友打电话,让她待会来我家的时候别穿绿色衣服 (好吧我没有女朋友),然后在短信里把我家地址发给了她。

我让女朋友来我家并且给女朋友提意见时发的是控制信息,也就是通过控制总线发的,而在短信里发送我家的地址给她,是通过地址总线发的,而她是通过数据总线走来我家的。

2.我的女朋友在离我家3816米的时候不知道还要往前走多少米,于是我准备给她飞鸽传书,但是我家giegie只能带写了3个数字的字条 (写了4个数字的字条太重了它飞不起来) ,于是我往一张纸条里写了一个300,另一张纸条里写了一个816,让两只giegie一起飞,女朋友收到后 (可能) 会知道我的意思,也就是300 * 10 + 816,也就是说你往前走3816米就会到我家啦。

3.这就是8086的物理地址表示方式,CPU地址总线有20条,也就是说地址总线可以一次表示一个20位二进制数,这个20位二进制数有220种可能性,地址总线是拿来表示CPU的物理内存的,也就是说20位二进制数可以表示220个内存单元,一个单元是一个字节,所以这样的地址总线可以表示的CPU大小为220 * 1Byte = 210 * 210 Byte = 1024 * 1KB = 1M,也就是说,这样的20条地址总线最多可以表示1M的CPU,但是8086的CPU只有16位的寄存器,如果说CPU要传出一个20位物理地址的话,起码需要两个寄存器。
可能Intel开发人员觉得一个寄存器用16位,另一个寄存器用4位这种方法比较浪费寄存器空间(也可能是他们觉得这种方法逼格不够),所以他们想了一个骚一点的方法,两个寄存器的所有位都要使用。
举个粒子

为了表示方便,我用一个516进制数来表示一个20位二进制数,现在要表示0x10ABC这个数;
可以把这个数拆成0x100000x00ABC,
而0x10000往右移一位,相当于它对应的二进制数往右移4位,变成了0x1000,这个时候它就是162进制啦,
并且要让0x00ABC也可以用416进制数来表示,这样就可以用两个16位寄存器来表示20位地址了,
总结一下,将20位二进制数用某种方式拆分成为两个数,将拆分后的第一个20位二进制数往右移4位,
变成16位二进制数,存入一个16位寄存器中,拆分后的第二个数天然就可以用16位二进制表示,所以也把它存
进另一个16位寄存器中,再把这两个寄存器的数据全部放入地址总线中从CPU中输出,在CPU外部,有一个地址
加法器,可以按照前面提到的算术过程反过来算出真正的物理地址,这样就把CPU里的物理地址搬到了外边儿
看似步骤有些冗余,但这是汇编必须要考虑的东西,也就是一个数字到底是存放在哪里的,以及存放容器够不够放这个数字。

以上便是8086的物理地址表示方式,前面提到的两个寄存器就是段地址寄存器和偏移地址寄存器;
个人感觉很多书很多帖子在8086物理地址的描述上都没有我写的细,在CSDN上搜到的关于这个的帖子感觉都是复制粘贴出来的,要么就是直接说8086用两个寄存器,要么就是抄的王爽老师的书……

四、存储器的演进

1.潘金莲告诉西门庆,你经过我家楼下的时候,如果看到窗台上的蜡烛是燃着的,你就进来,如果蜡烛是熄灭的,你可万万不能来,因为你可能会被武松打死;
潘骚实际上用蜡烛来传递了信息;

2.进入漆黑的房间时,我会下意识的按下开关,把灯打开,灯从不亮的状态转移到了亮的状态,这其实是类似于二进制的,也就是说灯管 + 电 + 人手就可以传递信息了;

3.抽象一点的说,通过消耗某种资源,可以让某个东西在足够长的时间里保持某种状态,让人或机器获取并理解;如果说要让灯管来传递信息的话,实际上需要消耗两种资源—负责开关的人、电能,电已经作为了一种消耗资源,我们也得尽量让电去控制开关;

4.继电器就是这样一个东西,它通电之后可以控制一个小锤锤去捶开关,但这实际上是电能转化为动能来使用;计算机里真正使用的存储器是结型场效应管,它和三极管其实差不太多,但是在某些方面比三极管要优秀,比如它很省电;

翻看了郑益慧教授的模电才勉强看懂,g极为栅极,它与下面的PN半导体因为二氧化硅而绝缘,所以省电啦
在这里插入图片描述
(剩下的挖个坑,期末考试过后再补

N - 2、C语言结构体在汇编层面的分析
编写一个很简单的C代码

#include <stdio.h>
struct User{
   
    int age;
    char *name;
    int money;
    long money2;
};
int main() {
   
    struct User user = {
   17, "Fakeraaaaaaaaaa", 1000, 3000};
    struct User *p = &user;
    printf("user's address: %p\n",&user);
    printf("p->age: %d\n", p->age);
    printf("age's address: %p\n" ,&(p->age));
    printf("p->name: %s\n", p->name);
    printf("name's address: %p\n" ,&(p->name));
    printf("p->money: %d\n", p
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值