汇编内存详解(如何用汇编语言读取内存值)

本文目录
- 如何用汇编语言读取内存值
- 汇编语言内存单元
- 汇编中的内存单元
- 汇编问题,内存分配的问题
- 我想要学汇编,可对内存地址和它的存储机制不明白,请各位不吝赐教,我还会追加分的,先谢了!
- 汇编指令在内存中是什么样子的
- 汇编语言内存中数据存放
- 汇编语言中的内存操作数是什么
- 汇编高手来说下内存对齐背后CPU究竟是怎么操作的
如何用汇编语言读取内存值
汇编语言读取内存的方式有两种:立即数寻址(包括在编译器中的变量地址),寄存器寻址。就拿80X86汇编来说,简单的使用MOV指令就可以完成对内存地址的读写,一下是立即数寻址和寄存器寻址实现内存读写的例子:
MOV AX, ;立即数寻址,将AX寄存器中放入偏移地址8000中的内容
MOV AX, ;寄存器寻址,将SI寄存器中的值作为地址,SI寄存器中存放的地址中 内容送到AX寄存器中。另外,任何通用寄存
(AX,BX,CX,DX,SI,DI,BP,SP)都可以放入方括号中行寻址
NUMBER DW 1234H ;变量地址定义
...
MOV AX, ;将NUMBER的地址进行寻址,然后将地址内的内容送入AX寄存 器中
需要注意的是,如果需要往立即数地址中直接写入或读取数据,则需要添加数据的大小标识符,否则编译器会产生错误。如下:
MOV ,1234H ;错误的指令!
MOV WORD PTR ,1234H ;正确,往偏移地址8000的内存位置中放入WORD类型的数据1234H
汇编语言内存单元
物理地址就是数据在内存中实际存放的位置.因为8086或8088有20条地址线,寻址能力有2的20次方,1MBit.而8086或8088内部寄存器是是16位的,无法用一个位完全表示出来.所以采用段首地址+偏移量两个寄存器来表示的方式,俗称PC或CS:IP来表示一个实际的物理地址,这就是所谓的虚拟地址.例如段首地址为0000H,而偏移量的范围就在0000H-FFFFH之间,就表示00000H-0FFFFH的实际内存单元.就是说一个段的大小在64Kb.
SUB1 DB 03H,35H 这个命令中,SUB1表示存放03H,35H这两个数据的首地址,相当于C语言中字符串数组的首地址.假如这个SUB1在数据段中,有专门的数据段寄存器DS,它的实际地址就是DS:SUB1
汇编中的内存单元
汇编语言,里面只有三种说法:寄存器、存储器 和 IO接口。
当年,并没有““内存””的说法。把 BUF 称为““内存单元””,是非专业人士的发挥。
数据段、代码段、附加段...,这些都是在存储器里面。
BUF DB 12H
这条语句经过编译、连接,运行的时候,BUF 就在存储器里面,占用了一个字节。
BUF,是这个字节的地址,12H,是字节的内容。
利用 BUF 可以对该字节进行读、写,BUF 也就称为““变量名””;
它实际上是用自定义的符号,代表了变量的地址,所以也叫做““符号地址””。
汇编问题,内存分配的问题
是单片机汇编还是8086汇编?
如果是8086汇编的话,基本原则是高地址存高字节,低地址存低字节,所以从0100h开始的内存单元里依次是($为取地址符)
04h,00h,05h,01h,02h,00h,01h,00h(ary
dw
0004h,0102h+3,0002h,0001h)
08h,07h,06h,05h(equ不占用内存单元,cnt=0108h-0100h=0008h)
(db
08h,07h,06h,05h)
我想要学汇编,可对内存地址和它的存储机制不明白,请各位不吝赐教,我还会追加分的,先谢了!
先说16位的:
因为总线限制,所以CPU可以访问1MB内存,但是由于只能使用16位寻址,一个16位无符号整数最大只能表示2的16次方大小的内存,即64kb,所以引入了一组"段寄存器",用于内存寻址,其格式为:"",表示访问内存地址0x11000的内容。有一点要注意,16位段寄存器只能是类似0x1000,0x2000,0x3000,...,0xf000的值,并且都要先装入ds段寄存器才能生效
32位:
段寄存器依然存在,但是意义不同了,其数值一般为8的整数倍,并且一般都由操作系统来帮我们设定。32位段寄存器中记录了其起始内存地址和可寻址的内存范围等信息。抛开操作系统的原因,一般我们都可以对4GB内存进行寻址,所以段寄存器的作用就不如以前明显甚至很多情况下都被忽略了。
总体上说:
我们一般访问内存都先要给出一个内存地址,然后才能对内存进行访问。不过汇编器和CPU替我们省略了一些内容,比如对数据段进行寻址,默认是使用DS段寄存器的,在汇编中格式为:
举个例子,在C中用个指针:unsigned long *p=0x12345678;就可以通过指针对0x12345678地址所指向的内容进行操作。而在汇编中,0x12345678只是一个值,要想对其内容进行操作,就必须使用等,其中的ds可以省略,但如果要对非ds段中的内容寻址就不能省略相应段寄存器
汇编指令在内存中是什么样子的
嘿嘿 俺来帮你回答
1 汇编指令由操作码和操作数组成 如:mov ax,0
mov为操作数 表示指令的功能(是传送指令)
ax,0是2个操作数 即0(0000H)为源操作数 ax为目的操作数
该指令就是 将源操作数传送给目的操作数 从ax可以看出是一条16位的传送指令
2 mov ax,0在内存中的机器指令是B8 00 00
B8 是操作码 表示是一条以ax为目的操作数的传送指令(操作数ax为寄存器寻址 隐含在操作码 中,00 00 表示的是一个16位的立即数即0000H 低8位在前 高8位在后。
3 汇编指令在内存中 就是以B8 00 00机器指令表示的二进制代码。
呵呵 满意 就选满意回答
汇编语言内存中数据存放
22 低地址
11
44
33 高地址
每个dw的高地址存放高位数据,低地址存放低位数据。
8086汇编中数据是存放在数据段的,所有从低地址到高地址的存放。你在访问3344H时可以直接用来访问。
需要区别的是windows的栈内存,是从高地址到低地址存放的。
汇编语言中的内存操作数是什么
指如
mov ax,mydata
...
mydata dw ?
中 mydata 这样的变量,其存储于某内存区域,因此叫内存操作数。
补充:汇编语言是汇编指令集、伪指令集和使用它们规则的统称,使用具有一定含义的符号为助忆符,用指令助忆符、符号地址等组成的符号指令称为汇编格式指令。
汇编语言是一门重要的程序设计语言。下面列举了至少4本名叫《汇编语言》的图书和教材,并简要介绍了高校计算机相关专业在开设“汇编语言”课程方面的一些情况。
汇编高手来说下内存对齐背后CPU究竟是怎么操作的
内存对齐:
我们知道现代计算机体系中CPU按照双字、字、字节访问存储内存,并通过总线进行传输,若未经一定规则的对齐,CPU的访址操作与总线的传输操作将会异常的复杂,所以现代编译器中都会对内存进行自动的对齐。
1.内存对齐系数
说道内存对齐,就不得不说内存对齐系数, 对齐系数最简单的设置方法是使用 #pragma pack(n)进行设置,这部分点进链接在我的文章内有详细说明!
2.sizeof
说到内存对齐第二个不得不说的就是sizeof,它的基本作用是判断数据类型或者表达式长度,要注意的是这不是一个函数,而是一个C++中的关键字!字节数的计算在程序编译时进行,而不是在程序执行的过程中才计算出来!
3.类型的长度与数据成员对齐
你的计算机中,数据类型的长度指的就是在你的计算机中对数据类型使用sizeof得到的结果,当然这个在各种不同的编译环境下得到的结果是不同的。
比如在32位Visual Studio环境下:
cout 《《 sizeof(char) 《《 endl; // 1
cout 《《 sizeof(short) 《《 endl; // 2
cout 《《 sizeof(int) 《《 endl; // 4
cout 《《 sizeof(long) 《《 endl; // 4
cout 《《 sizeof(double) 《《 endl; // 8
而在64位G++编译环境下:
cout 《《 sizeof(char) 《《 endl; // 1
cout 《《 sizeof(short) 《《 endl; // 2
cout 《《 sizeof(int) 《《 endl; // 4
cout 《《 sizeof(long) 《《 endl; // 8
cout 《《 sizeof(double) 《《 endl; // 8
下面我将在32位Visual Studio环境下讲解数据成员对齐:
首先我们要清楚结构体struct中的成员在内存中的分配是连续的,struct内的首地址也就是struct内第一个数据成员的地址,换句话说struct内第一个数据成员离struct开始的距离offset = 0。
数据成员对齐的规则就是,而在第一个成员之后,每个成员距离struct首地址的距离 offset, 都是struct内成员自身长度(sizeof) 与 #pragma pack(n)中的n的最小值的整数倍,如果未经对齐时不满足这个规则,在对齐时就会在这个成员前填充空子节以使其达到数据成员对齐。
默认n为8时:
struct {
char a;
double b;
} myStruct;
cout 《《 sizeof myStruct 《《 endl; // 16
cout 《《 (int *)&myStruct.a 《《 endl; // 0024F898
cout 《《 &myStruct.b 《《 endl; // 0024F8A0(因运行时而异)
当设置n为4也就是min(sizeof(double), n) = 4 时:
#pragma pack(4)
struct {
char a;
double b;
} myStruct;
cout 《《 sizeof myStruct 《《 endl; // 12
cout 《《 (int *)&myStruct.a 《《 endl; // 0046F76C
cout 《《 &myStruct.b 《《 endl; // 0046F770
第一个例子时,最小值为8,填充7个字节到char a 之后。
第二个例子时,最小值为4,填充3个字节到char a之后。
4.整体对齐
编译器在进行过数据成员对齐之后,还要进行整体对齐。与数据对齐相似但不是完全相同, 如果数据对齐完成时struct的大小不是 struct内成员自身长度最大值(sizeof) 与 #pragma pack(n)中的n的最小值的整数倍。(注意这里是成员中长度最大的那个与n比较,而不是特定的一个成员。)就要在struct的最后添加空字节直到对齐。
当设置n为4也就是min(sizeof(short), n) = 2 时:
#pragma pack(4)
struct {
char a;
short b;
char c;
} myStruct;
cout 《《 sizeof myStruct 《《 endl; // 6
cout 《《 (int *)&myStruct.a 《《 endl; // 003DFED0
cout 《《 &myStruct.b 《《 endl; // 003DFED2
cout 《《 (int *)&myStruct.c 《《 endl; // 003DFED4
在上面的例子中,char a offset为0 因成员对齐占据无需成员对齐,但此时struct的大小是2+2+1 = 5字节,不是2的整数倍,所以我们要填充空子节在最后直到struct大小达到2的整数倍,这就是整体对齐。
经过了数据成员对齐与整体对齐之后内存对齐就完成了,如果深入思考上述规则还会发现:即使是同样数目与数量的数据成员,在摆放的顺序不同时struct的大小也会不同,下面就是一个例子:
这样摆放是12字节:
12字节.png
结果是12字节.png
摆放方式改变时结果确变成了8字节:
8字节.png
却变成了8字节.png
由于这种特性,如果在网络编程或相关内存操作时如果不加以注意的话,就会造成隐秘而难以纠正的错误,请大家务必小心!

更多文章:
线程池内中断某个线程(如何终止 android线程池中的任务)
2026年1月7日 07:15
为什么mysql没有bin目录(我在windows7下面安装mysql怎么会没有bin目录呢)
2026年2月7日 02:30
进程管理器端口(win7系统怎么查看端口被哪个进程占用情况呢)
2026年4月9日 11:45
translate的用法及其词组(英语Arrival Site怎么翻译)
2026年7月16日 00:00
grassland(grassland怎么读 英语grassland怎么读)
2025年12月10日 09:45
elementui和bootstrap 哪个好(学习bootstrap还是vue好)
2026年4月1日 10:45
下载jquery最新版本教程(怎么引用bootstrap轮播图)
2026年8月26日 01:45
二次分式怎么求值域(如果是二次分式函数,那么应该怎么求值域)
2026年9月18日 04:30
手机上怎么显示html图片(html格式的图片在手机上怎么能打开)
2026年8月9日 01:30
js的replaceall(js 怎么替换不了 | 这个符号)
2026年9月16日 13:00
安卓activity软件(activity(Android组件中最重要的四大组件之一)详细资料大全)
2026年7月30日 07:00














