汇编语言基础(二)

汇编学习教程:定义不同的段 引言 截至目前为止,我们所编写的汇编程序中有且只有一个段,那就是代码段。代码段当然是必不可少的,要不然我们的代码放在哪里呢! 在上篇博文中,我们学习了如何在代码段中申请空间,将申请过来的空间用来当作数据段和栈段来使用。这样的话,也就是说我们源程序中,数据段和栈段都在代码段内,它们共用同一个段地址。 这样就导致我们在编程时,要注意何处是数据,何处是栈,何处是代码。所以出现了两个问题: 1、把它们放在一个段中使程序显得混乱。程序结构不鲜明,不符合开发规范 2、我们上篇博文中的程序中处理的数据很少,且 阅读详情

函数的调用


一、函数调用

(一)call和ret指令

call指令: 相当于用来调用封装的方法
ret指令: 相当于retun指令

例子:
以下代码是输出一个Hello

assume cs:code, ds:data, ss:stack
;栈段
stack segment
	db 100 dup(0)  //创建了100个0当做栈段
stack ends

;数据段
data segment
	db 100 dup(0)
	string db 'Hello!$'  //定义一个字符串,起个名字叫 string
data ends

;代码段
code segment
start:
	;手动赋值 ds,ss
	mov ax, stack
	mov ss, ax
	mov ax, data
	mov ds, ax
	;业务逻辑
	
	;ds:dx 在内存中找到字符串
	mov dx, offset string
	;输出字符串
	mov ax, 9h
	int 21h

	;代码退出
	mov ax, 4c00h
	int 21h
code ends
end start

现在我需要输出3个Hello(需要把输出封装一下,然后调用)

assume cs:code, ds:data, ss:stack
;栈段
stack segment
	db 100 dup(0)  //创建了100个0当做栈段
stack ends

;数据段
data segment
	db 100 dup(0)
	string db 'Hello!$'  //定义一个字符串,起个名字叫 string
data ends

;代码段
code segment
start:
	;手动赋值 ds,ss
	mov ax, stack
	mov ss, ax
	mov ax, data
	mov ds, ax
	;业务逻辑
	call print    //调用输出语句封装的方法

	;代码退出
	mov ax, 4c00h
	int 21h
	
;把字符串封装成以下形式
print: 
	mov dx, offset string
	mov ax, 9h
	int 21h	
	ret   //记着一定要ret出去
code ends
end start

(二)call和ret原理解析

call就是将下一条指令的偏移地址入栈,然后再跳转到对应的代码处
ret:将栈顶的值出栈,赋值给IP,IP就是偏移地址CS:IP
所以ret以后,cpu还能找到继续执行的指令

注意:既然是ret是让栈顶的值出栈赋值给IP,那就不能在封装的方法中,做入栈操作(push ax),否则将会修改栈顶的值

(三)函数的返回值

思路:
1.最常用:
首先要计算出23值,然后方到寄存器ax中,在ret返回
然后回到业务逻辑这,可以直接接收用bx寄存器(mov bx, ax)
2.
在封装的方法中: mov [0], ax 把值放到ds:[0] 内存的数据段中
在业务逻辑这接收: mov bx, [0] 把值从ds:[0]中取出来放到 bx

assume cs:code, ds:data, ss:stack
;栈段
stack segment
	db 100 dup(0)  //创建了100个0当做栈段
stack ends

;数据段
data segment
	db 100 dup(0)
	string db 'Hello!$'  //定义一个字符串,起个名字叫 string
data ends

;代码段
code segment
start:
	;手动赋值 ds,ss
	mov ax, stack
	mov ss, ax
	mov ax, data
	mov ds, ax
	;业务逻辑
	call match    
	mov bx, ax    //直接取ax的值,放到bx中就行  方式一
	
	call match1   //方法二
	mov bx, [0]   //其实是将内存地址ds:[0]中值取出放到 bx中了
	;代码退出
	mov ax, 4c00h
	int 21h
	
;我现在想着返回一个2的3次方
match: 
	;计算出2的3次方数值,然后方到ax寄存器中
	mov ax, 2
	add ax,ax
	add ax,ax
	ret   //记着一定要ret出去
	
;对应的方法二
match2: 
	;计算出2的3次方数值,然后方到ax寄存器中
	mov ax, 2
	add ax,ax
	add ax,ax
	mov [0],ax //其实是将ax的值,放到内存地址为ds:[0]的内存中了
	ret   //记着一定要ret出去
code ends
end start

(四)函数传参

例如:我想着把10和20相加
方法1:参考返回值,在代码段把10放到cx寄存器(mov cx, 10),把20放到dx寄存器(mov dx, 20),在封装方法中把cx和dx相加(mov ax,cx ; add ax,dx)

assume cs:code, ds:data, ss:stack
;栈段
stack segment
	db 100 dup(0)  //创建了100个0当做栈段
stack ends

;数据段
data segment
	db 100 dup(0)
	string db 'Hello!$'  //定义一个字符串,起个名字叫 string
data ends

;代码段
code segment
start:
	;手动赋值 ds,ss
	mov ax, stack
	mov ss, ax
	mov ax, data
	mov ds, ax
	;业务逻辑
	mov cx,10
	mov dx,20
	call sum    
	mov bx, ax    //直接取ax的值,放到bx中就行
	;代码退出
	mov ax, 4c00h
	int 21h
	
;返回值一般放到ax寄存器中
;传参2个(分别放到cx, dx寄存器中)
sum:
	mov ax, cx
	add ax, dx
	ret
	
code ends
end start

方法2:
对于多个参数,一般是通过栈来传参数,在代码段把参数入栈,在封装方法中,取出。
这个取出需要注意,并不是pop取出,不能移动SP指针,而是通过SP+2这样来取值

注意: 由于系统会把调用封装方法的下一行指令的偏移地址放到栈顶,ret的时候在从栈顶取出
所以在封装的函数中,不能改变SP指针的位置

assume cs:code, ds:data, ss:stack
;栈段
stack segment
	db 100 dup(0) //创建100个0当做栈段等着别人来用
stack ends

;数据段
data segment
	db 100 dup(0) 
data ends

;代码段
code segment
start:
	;手动赋值ss
	mov ax, stack
	mov ss, ax
	;手动赋值ds
	mov ax, data
	mov ds, ax
	//业务逻辑处理
	;入栈2个参数
	push 1122h
	push 3344h
	call sum
	add sp,4 ;涉及到栈平衡
	
	mov bx, ax
	mov ax, 4c00h //退出
	int 21h
code ends
;返回值放到ax中
;传参
sum:
	;入栈以后如图1,但是可不能pop取值,如果pop ax,指针sp就会往下移,ret就会出错
	;所以
	mov bp, sp  ;把sp指针给bp,bp是辅助sp指针
	mov ax, ss:[bp+2]   ;通过ss:[0] ,栈:偏移地址取出来,类似ds:[0]
	add ax, ss:[bp+4]
	ret
end start

在这里插入图片描述

二、栈平衡

栈平衡: 简单总结 栈使用之前和使用之后,sp指针要保持一样

(一)栈平衡原理分析

原理分析:
如上图1所示,这是当你调用1 个函数(call sum)以后栈地址的分布。如果此时再调用第二个函数的时候,sp就会从40000H开始,继续往上移动,而不是从栈顶了,如图2
在这里插入图片描述

当在调用第三次的时候,就会又累加,因此造成栈空间浪费,调用多了造成栈溢出。
因此需要解决这种情况。如何解决????
只需要将sp+4就可以解决,例如图1,第一个函数结束以后,就add sp, 4(指针就回到栈顶了)
这样就可以将原来的数据覆盖了,从而实现了内存销毁,保持栈平衡!

1.外平衡

把add sp,4 放到函数调用结束,就是外平衡!!!

push 1122h
push 3344h
call sum
add sp,4 ;涉及到栈平衡

2.内平衡

在函数返回值ret中,ret 4,这是内平衡!

sum:
	mov bp, sp  ;把sp指针给bp,bp是辅助sp指针
	mov ax, ss:[bp+2]   ;通过ss:[0] ,栈:偏移地址取出来,类似ds:[0]
	add ax, ss:[bp+4]
	ret   4

注意 ret 4 还有add sp,4 这个4可不是乱写的,是根据你入栈的空间来的,你占用多少,你就加回去多少

(二)函数递归

函数递归也会造成栈溢出,函数的递归是发生在函数内部,函数并没有结束,无法将sp指针移动
如下错误代码,会造成递归

assume cs:code, ds:data, ss:stack
;栈段
stack segment
	db 100 dup(0) //创建100个0当做栈段等着别人来用
stack ends

;数据段
data segment
	db 100 dup(0) 
data ends

;代码段
code segment
start:
	;手动赋值ss
	mov ax, stack
	mov ss, ax
	;手动赋值ds
	mov ax, data
	mov ds, ax
	//业务逻辑处理
	;入栈2个参数
	push 1122h
	push 3344h
	call sum
	add sp,4 ;涉及到栈平衡
	
	mov bx, ax
	mov ax, 4c00h //退出
	int 21h
code ends
;返回值放到ax中
;传参
sum:
	;入栈以后如图1,但是可不能pop取值,如果pop ax,指针sp就会往下移,ret就会出错
	;所以
	mov bp, sp  ;把sp指针给bp,bp是辅助sp指针
	mov ax, ss:[bp+2]   ;通过ss:[0] ,栈:偏移地址取出来,类似ds:[0]
	add ax, ss:[bp+4]
	call sum ;在次调用,这样造成了循环
	ret
end start

(三)函数中调用函数与函数结束调用函数比较

问题:
在封装的函数1中,调用函数2,在函数2中调用涵数3,…这样效率高 ???
还是在函数1调用结束以后,调用函数2,函数2结束调用函数3,…这样效率高?
分析:
在函数1中调用函数2,此时函数1并没有结束,就调用了函数2,因此,栈空间开辟了函数1和2的。
同理,在函数2还未结束的时候就调用函数3,此时栈空间继续开辟,以此类推,调用的函数越多,栈空间占用的越多,直到最后一个函数调用结束,才能依次销毁,最终返回栈顶!
而,在函数1调用结束以后,在调用函数2,栈空间就不会依次累加,2结束以后调用3,也不会累加!!!
结论:
函数调用结束以后在调用函数 > 函数内调用函数

(四)函数的约定

__cdecl :参数从右至左入栈,是外平衡
sum (a, b)
push b
push a
add sp, 4

__stdcall: 参数从右至左入栈,是内平衡
sum (a, b)
push b
push a
ret 4

__fastcall: 优先使用寄存器传参,寄存器不够用,在用push从右至左,并且是内平衡
sum (a, b, c, d, e, f)
mov bx ,a
mov cx, b
mov dx, c
push f
push e
push d
ret 6
Xcode使用的就是__fastcall

总结:函数调用的本质

1.参数: push参数值
2.返回值: 一般都放在ax寄存器中
1.栈平衡: 保持栈平衡

三、函数的局部变量

例如:一段函数如下,分析其中的汇编流程

int sum (int a, int b)
{ 
   int c = 3;
   int d = 4;
   int e = c+d
   return a + b + e;
}
int main (int argc, char*argv[])
{
	sum (10, 2)
	return 0;
}

转换汇编流程:

assume cs:code, ds:data, ss:stack
;栈段
stack segment
	db 100 dup(0) //创建100个0当做栈段等着别人来用
stack ends

;数据段
data segment
	db 100 dup(0) 
data ends

;代码段
code segment
start:
	;手动赋值ss
	mov ax, stack
	mov ss, ax
	;手动赋值ds
	mov ax, data
	mov ds, ax
	//业务逻辑处理
	;入栈2个参数
	push 1122h
	push 3344h
	call sum
	add sp,4 ;涉及到栈平衡
	
	mov bx, ax
	mov ax, 4c00h //退出
	int 21h
code ends
;返回值放到ax中
;传参
sum:
	mov bp,sp ;先把sp的值赋值给bp
	sub sp,10 ;在给sp-10,向上拉伸10个字节空间,用来放局部变量
	;定义2个局部变量
	mov word prt ss:[bp-2],3
	mov word ptr ss:[bp-4],4
	mov ax, ss:[bp-2] ;把3取出来给了ax
	add ax, ss:[bp-4] ;ax在和4相加给了ax
	mov word ptr ss:[bp-6],ax ;在把值继续存入bp-6中
	
	mov ax, ss:[bp+2] ;取出参数3344
	add ax, ss:[bp+4] ;将3344和1122相加
	add ax, ss:[bp-6]  ;取出局部变量的结果7,在相加
	;恢复sp
	mov sp, bp
	ret
end start

(一)局部变量流程分析

在这里插入图片描述

(二)bp指针无法恢复问题

但是,如果在函数中再次调用另一段函数,会出现什么问题?
在这里插入图片描述

(三)保护bp指针

因此我们需要把bp的值进行保护起来!
在这里插入图片描述
保护了bp寄存器需要注意一下,取参数的时候就不是ss:[bp+2]了,就是ss:[bp+4] 和 ss:[bp+6] 了

‘bp-’ 往上走肯定是局部变量!
‘bp+’ 往下走肯定是参数!

(四)保护其它寄存器

在函数当中,有的时候可能还会用到其它的通用寄存器,例如:si di bx寄存器,因此需要把他们原有的值保护起来
保护方式同样和bp一样。

assume cs:code, ds:data, ss:stack
;栈段
stack segment
	db 100 dup(0) //创建100个0当做栈段等着别人来用
stack ends

;数据段
data segment
	db 100 dup(0) 
data ends

;代码段
code segment
start:
	;手动赋值ss
	mov ax, stack
	mov ss, ax
	;手动赋值ds
	mov ax, data
	mov ds, ax
	//业务逻辑处理
	;入栈2个参数
	push 1122h
	push 3344h
	call sum
	add sp,4 ;涉及到栈平衡
	
	mov bx, ax
	mov ax, 4c00h //退出
	int 21h
code ends
;返回值放到ax中
;传参
sum:
	push bp  ;把原有bp的值保护起来
	mov bp,sp ;在把sp的值赋值给bp
	sub sp,10 ;在给sp-10,向上拉伸10个字节空间,用来放局部变量
	;保护其它寄存器
	push si
	push di
	push bx

	;业务逻辑了----定义2个局部变量
	mov word prt ss:[bp-2],3
	mov word ptr ss:[bp-4],4
	mov ax, ss:[bp-2] ;把3取出来给了ax
	add ax, ss:[bp-4] ;ax在和4相加给了ax
	mov word ptr ss:[bp-6],ax ;在把值继续存入bp-6中
	
	mov ax, ss:[bp+4] ;取出参数3344 
	add ax, ss:[bp+6] ;将3344和1122相加
	add ax, ss:[bp-6]  ;取出局部变量的结果7,在相加

	;恢复其它寄存器,注意恢复其它寄存器的顺序
	pop bx
	pop di
	pop si
	;恢复sp
	mov sp, bp
	;恢复bp
	pop bp
	
	ret
end start

用图片区域来表示栈空间分布情况:
在这里插入图片描述

(五)保护局部变量的空间

如果说你拉伸一段栈空间,(sub sp,10), 正好sp指针所指的位置是一个退出函数,那么程序就会出问题。
因为你永远不知道你拉伸的空间内之前存在什么指令。因此像这种不确定的,我们需要填充一堆数据来覆盖它。
在windows中填充的是 int 3 (CCCC)指令,也就是一堆断点指令。

;只从sum函数写起
sum:
	push bp  ;把原有bp的值保护起来
	mov bp,sp ;在把sp的值赋值给bp
	sub sp,10 ;在给sp-10,向上拉伸10个字节空间,用来放局部变量
	
	;保护其它寄存器
	push si
	push di
	push bx
	
	;给局部变量填充int 3(cccc)指令
	;stosw的作用,将ax的值拷贝到es:di中,同时di的值会+2
	mov ax, 0cccch
	;让es=ss,不能这样写mov es,ss ,必须通过一个中间变量
	mov bx, ss
	mov es, bx
	;让di-10,和也就是整个局部变量的最上面(一开始不是拉伸了10个空间吗)
	;因为每次复制di都会+2,
	mov di,bp
	sub di,10 ;
	;cx觉得这个复制,执行几次,
	mov cx,5 ;执行5次整个di+10了就,di就会回到bp的位置
	rep stosw
	;rep 的作用是重复执行某个命令(执行此时是由cx决定)


	;业务逻辑了----定义2个局部变量
	mov word prt ss:[bp-2],3
	mov word ptr ss:[bp-4],4
	mov ax, ss:[bp-2] ;把3取出来给了ax
	add ax, ss:[bp-4] ;ax在和4相加给了ax
	mov word ptr ss:[bp-6],ax ;在把值继续存入bp-6中
	
	mov ax, ss:[bp+4] ;取出参数3344 
	add ax, ss:[bp+6] ;将3344和1122相加
	add ax, ss:[bp-6]  ;取出局部变量的结果7,在相加

	;恢复其它寄存器,注意恢复其它寄存器的顺序
	pop bx
	pop di
	pop si
	;恢复sp
	mov sp, bp
	;恢复bp
	pop bp

总结:函数调用本质(内存)

1. push参数
2. push函数返回地址
3. push bp (保留之前bp的值)
4. mov bp, sp (保留sp之前的值,方便以后恢复)
5. sub sp,空间大小 (拉伸空间给局部变量)
6. 保护可能用到其它的寄存器
7. 使用cc(int 3)填充局部变量空间
8. ----------------执行业务逻辑----------
9. 恢复其它寄存器之前的值
10. mov sp, bp (恢复sp)
11. pop bp (恢复bp)
12. ret (将函数的返回值出栈,执行下一条指令)
13. 恢复栈平衡 (add sp, 参数所占空间)

汇编学习教程:bp 寄存器 我们在此前的学习中已经了解了CPU中众多的寄存器,比如通用寄存器 AX、BX、CX、DX,还有段寄存器 CS、DS、SS、ES。在内存访问和灵活寻址的学习中,我们重点学习了 BX 寄存器和 CX 寄存器。BX 寄存器通常配合 DS段寄存器来实现内存访问,而 CX 寄存器则配合 Loop 指令实现循环控制。此外,除了上述我们提到的寄存器外,还有几个特殊的寄存器。IP 寄存器,全称“指令指针寄存器”,配合 CS 段寄存器使用,任意时刻 CPU 将 CS:IP 指向的地址下的数据当作代码来执行; 阅读详情

相关推荐

汇编语言源程序基本格式

汇编语言源程序基本格式 基本格式 DATA SEGMENT ;数据段 . . . . . . . . . DATA ENDS STACK1 SEGMENT PARA STACK ;堆栈段 DW 20H DUP (0) STACK1 ENDS CODE SEGMENT ;代码段 ASSUME CS: CODE , DS:DATA,ES:EXTERA BEING(@): … … … . . . . . . . . . . . .指令序列 CODE EN

weixin_48437766的博客 1472

汇编程序设计

伪指令是一些看起来像指令,但实际上并不是CPU可以直接执行的指令。它们更像是一种特殊的命令,由汇编器(或编译器)处理。 伪指令的功能主要是帮助程序员更方便地编写和组织汇编程序。它们可以用来定义数据、布局程序、定义常量和符号,以及进行条件编译等操作。 举个例子,如果我们想在汇编程序中定义一些数据,比如一系列的数字或字符,我们可以使用伪指令来简化操作。通过使用伪指令,我们可以直接写下这些数字或字符,并告诉汇编器将它们保存在内存中的特定位置。伪指令会在编译时被汇编器解析,生成相应的机器码或控制信息。 另外,

2301_76771985的博客 2960

【ARM汇编语言基础】-ARM架构基础(二)

ARM架构异常处理与执行状态分析 本文详细介绍了ARM架构中的异常处理机制和执行状态特性。在异常处理方面,文章阐述了同步异常(如无效指令执行)和异步异常(如中断)的区别,以及异常级别变化的处理流程,包括SVC、HVC、SMC等系统调用指令和异常向量表的组织结构。同时解释了安全状态切换和SMC异常处理过程。 在执行状态方面,文章对比了AArch64和AArch32两种执行状态的特点。AArch64采用64位地址空间和A64指令集,支持更广泛的寄存器组;而AArch32保持与Armv7-A的兼容性,支持A32和

视觉与物联智能 597

微机原理寻址方法总结

复习

sher_chang的博客 525

【ARM汇编语言基础】- 操作系统基础(二)

本文摘要介绍了操作系统中的线程与内存管理基础知识。主要内容包括:线程机制、内存管理、内存页、内存保护、内存类型。

视觉与物联智能 471

树莓派与stm32通信超详细解答过程

笔者之前发过关于stm32与openmv通信的教程,在学习了几天opencv后,想实现树莓派4B与stm32进行通信。于是上网查询资料,最后实现了两者之间的通信,相信这对大多数电赛人都很有帮助,opencv的识别效果是远高于openmv以及K210的。在此我参考了以下资料辅助我学习,大家可以参考。基于树莓派4B与STM32的UART串口通信实验(代码开源)_树莓派4b串口波特率-优快云博客。

Halcyon0804的博客 5465

MASM汇编语言笔记(二)汇编语言基础

回车换行符 CR/LF 0dh,0ah 字符串以空字符0结尾 greetings BYTE "Good Morning",0 不初始化的值用?表示,例如 value BYTE ? DUP初始化多个字节,例如 array WORD 20 DUP(?) 遗留初始化伪指令DB,

zifei123的专栏 1176

Maven

是一款自动化构建工具,专注于Java项目的构建、依赖的管理。

weixin_58738870的博客 2163

汇编语言基础知识(二)

1.汇编语言首先进行编译,生成目标文件(.obj),然后通过连接器进行连接生成(.exe)文件。 2.段结束用ends,告知编译器程序结束用end,程序返回用mov ax,4c00H;int 21 3.masm是汇编语言的编译器 4.每一个程序都需要通过壳程序将其加载到内存中,比如dos中的command(DOS的shell)就是一个壳程序,debug也是一个壳程序。 5.将程序的入口地址传给cpu,程序就可以运行了。 6.inc bx 代表bx中的内容加1。 7.cx寄存器保存loop循环的次

liran2019的博客 711

CLion for Mac(m1)配置GCC编译器

条件:电脑已经下载过XCode 一. 下载HomeBrew homebrew是一款macos,linux下的包管理工具,我们需要使用他来下载GCC 下载方法: 1.打开终端(terminal) 2.输入 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" ps.有可能会遇到的问题 我当初下载挂了VPN,优快云上还有很多解决问题的方法,可以将错误信

supermario19的博客 7846

封神台靶场,为了小芳,冲之——cookie注入

第二个靶场 打开网站 找一下注入点 一般在新闻这种里面点开看看 先判断是否存在注入 有waf 尝试了很多方法绕过都没成功,/and/,aandnd,AnD等一系列都没绕过去,乌鸡鲅鱼 删掉id=169 发现 然后判断cookie注入 在搜索框输入 Javascript:alert(document.cookie=”id=”+escape(‘169’)); 然后弹窗了(其中 “id=” 取决URL中的id= escape中的数值也是URL中id=的值)返回刚刚的页面,把ID删除后一样能正常显示。说明服务器能

Wubuqing的博客 653

计算机基础(二):汇编语言与内存

汇编语言、内存结构

Flash~ 3230

保姆级教程:用BIGEMAP和Global Mapper搞定5米精度DEM高程数据下载与处理

本文提供了一份详细的5米精度DEM高程数据处理教程,涵盖从BIGEMAP下载到Global Mapper处理的完整流程。通过实战案例和避坑指南,帮助用户掌握高效下载DEM数据、优化等高线生成及坐标系转换的关键技巧,适用于GIS新手和专业人士。

weixin_34169322的博客 390

【汇编语言】寄存器(CPU工作原理)(二)—— 汇编指令的基础操作

汇编指令的基础操作

2301_80191662的博客 1267

MFC实现图书管理系统(附完整源码)

MFC实现图书管理系统(附完整源码)

希望我的博客,能帮上你解决学习中工作中所遇到的问题 801

飞牛fnNAS个人小账本导入微信账单

本文介绍了将微信支付账单导入ezBookkeeping个人记账系统的详细方法。首先通过微信申请导出账单文件,接收后需进行Excel预处理:删除前导行、添加账户和分类列、整理金额格式等。在ezBookkeeping中需预先设置"微信"分类和账户。导入时需注意列映射关系,包括交易时间、账户名称等关键字段的对应设置。文章还提到处理交易标签、格式转换等细节问题,并建议避免使用"修改余额"功能。该方法同样适用于支付宝账单导入,解决了直接导入可能出现的格式不兼容问题。

dgnankai的专栏 482

汇编语言基础二 —— CPU资源和存储器

CPU资源和存储器 计算机的硬件资源是用汇编语言编程所必须要了解的重要内容,因为汇编语言允许、也需要程序员直接使用这些硬件资源,只有这样才能编写出高效的目标代码。 在汇编语言中,需要访问的硬件资源主要有:CPU内部资源、存储器和I/O端口。本章将着重讲解CPU内部寄存器的命名、功能及其常见的用途,还要介绍存储器的分段管理模式、存储单元地址的表示法以及其物理地址的形成方式。 2.1 寄

Apple 607

AIGC算法工程师-面试八股文-2025年版本-算法八股文/工程八股文/开放式问题

​两年前整理了《AIGC算法工程师 面试八股文》,全网一共有100w读者看过,收到了很多小伙伴的催更。Diffusion的技术发展非常快,博主特意整理了最近两年最新的八股文,内容非常全面,涵盖算法八股文/工程八股文/开放式问题三个大类,希望能为求职的读者们带来帮助。

沉迷单车的追风少年 4185

汇编语言程序设计基础知识二

1、分析问题2、建立数据模型3、设计算法4、编制程序5、上机调试。

weixin_62224014的博客 1192

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

汇编语言基础归纳整理(二)

指令系统总结 8086CPU所提供的指令分为以下几大类。 1.传送指令 如mov,push,pop,xchg,in,out等都是传送指令,这些指令实现寄存器与寄存器、寄存器与内存单元、寄存器与端口之间的数据传送。 2.算术指令 如add,sub,mul,div,adc,sbb,inc,dec,cmp等都是算术指令,这些指令实现寄存器和内存中的数据的算术运算。 3.逻辑指令 如and,or,not,...

weixin_44613597的博客 310

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

x64汇编语言与逆向工程基础指南(二)

在内存中存储数字常量,字符串常量和变量

qq_74259765的博客 1496

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

【汇编语言基础】二、总线和CPU位宽

1根数据线一次传输1比特(0或1),8根数据线可以一次传送8比特(1字节),以此类推。例如,8088CPU的数据总线宽度为8,一次传送1字节数据;我们常说的“32位系统”、“64位系统”(当前大部分主流操作系统都为64位)指的就是CPU的位宽,即数据总线的宽度。假设CPU地址总线的宽度为N,则CPU可以访问的内存单元数量为2^N(每根地址线传送0或1)。在经典计算机架构(冯诺伊曼架构)中,计算机中有三根总线(BUS,拉丁文omnibus的简称)连接CPU和内存,分别是地址总线、数据总线和控制总线。

weixin_43031313的博客 1361

单片机基础之汇编语言入门学习(二)寄存器 及 简单汇编指令

程序的简要运行流程 1、程序加载到内存中 2、CPU找到程序即将执行指令位置,并执行程序 那么CPU是如何找到程序即将执行指令位置呢? –需要使用寄存器(CS:IP)寻址来确定即将执行指令位置 什么是寄存器 寄存器是CPU内的组成部分。有限存储容量的高速存储部件,他们可以用来暂存指令、数据和地址。 存在于CPU中 用于存储数据 速度快 数量有限 寄存器简介 一个二进制数 = 1位;8位=1字节;2字节=1字 8086CPU含有16个寄存器,所有的寄存器都是16位的,可以存放两个字节,即存放一个字。

肌肉猛男 944

8086汇编语言——使用数据段和栈段

;编写程序将data1段和data2段中的字节型数据依次相加,将结果存在data3段中。 ;ds保存data1的段地址,es保存data2的段地址,ss保存data3的段地址。 ;db用来定义字节型数据,这里定义了5个连续的字节型数据。 assume cs:code data1 segment db 1,2,3,4,5 data1 ends data2 segment db 6,7,8,9,10 data2 ends data3 segment db 0,0,.

zy010101博客 6057

嵌入式系统实验二ARM汇编基础编程资源介绍:掌握ARM汇编编程,提升嵌入式技能

嵌入式系统实验二ARM汇编基础编程资源介绍:掌握ARM汇编编程,提升嵌入式技能 去发现同类优质开源项目:https://gitcode.com/ 项目介绍 嵌入式系统实验二ARM汇编基础编程资源介绍是一个专为嵌入式开发者和学习者设计的学习资源,通过实验指导与汇编代码实例,帮助用户深入理解ARM处理器汇编语言的基本语法及其编程技巧。本资源涵盖了实验报告和汇编代码,旨在通过实践操作提升用户对嵌入式系统...

gitblog_06791的博客 362

c x86 汇编语言,[推荐]【看雪课程】从C语言追溯到X86汇编语言,开课啦!

立于江湖之上,还在担心没有一技傍身?一位良师引导,自是犹如神助,成长飞速。看雪讲师岭南散人将带领大家从C语言追溯到X86汇编语言,还在等什么? 快来跟随师傅学习吧!以下是《从C语言追溯到X86汇编语言》课程的具体内容,学习方式请直接移步文末哦!接下来就只剩下潜心修炼了!课程介绍这是一个演绎着刀光剑影的江湖--技术大神用代码指令在0与1的世界里飞檐走壁;各路侠客以独门绝技独步武林;正邪较量时各出奇招...

weixin_40007668的博客 302
上一篇: 汇编语言基础(一)
下一篇: OC对象的本质
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值