首页 > 其他分享 >四、常用寄存器

四、常用寄存器

时间:2024-11-25 17:56:07浏览次数:9  
标签:常用 16 mov 地址 寄存器 ax bx

DS:内存段地址寄存器

段地址、偏移地址与物理地址

  1. 内存中数据的地址由段地址和偏移地址组成,其中段地址乘以16再加上偏移地址就是真实的物理地址。

    对于16进制的数来说,乘以十六就是整体向左移一位,例如:0xFE * 16 = 0xFE0

  2. 物理地址可以由多种段地址+偏移地址组合而成

    例如物理地址:0x21F60都可以由下面段地址+偏移地址表示

    段地址 偏移地址
    0x2000 0x1F60
    0x2100 0x0F60
    0x21F0 0x0060
    0x21F6 0x0000
    0x1F00 0x2F60

操作DS

读写内存与DS寄存器的关系

读写内存中的数据需要知道该内存的地址,而地址是段地址+偏移地址组成的,其中段地址在ds寄存器中,偏移地址由手动指定。

我们指定偏移地址后,程序自动在ds中取出段地址,与我们指定的偏移地址组成实际的物理地址,从而操作该地址的数据。

所以在访问内存的数据前,要先设置ds段地址寄存器,再手动指定偏移地址

设置DS寄存器的注意事项

在8086CPU中,ds不支持直接将立即数放到ds中,要用另一个寄存器传输数据

mov bs,21f6		// 不支持这样写

mov ax,21f6		// 把段地址先写入另一个寄存器
mov ds,ax		// 再通过寄存器与寄存器传输数据的方式为ds传输数据

示例:操作0x21F60处的数据

mov ax,21f6
mov ds,ax		// 设置段地址为0x21f6
mov ax,[0]		// 设置偏移地址为0x0000,对应的物理地址为:0x21F60。并将该地址的值复制到ax中

image

add al,[0]		// 0x21f60处的值加上al中的值,结果放到al中
mov [0],bl		// 把bl的值复制到0x21f60
add [0],bh		// bh加上0x21f60处的值,结果放到0x21f60

CS-IP:代码地址寄存器

作用:CS存的是段地址,IP存的是偏移地址,代码从这两个寄存器指向的地址开始运行

示例:在地址:0x20000处写代码,并改变CS-IP寄存器,从0x20000处开始运行代码

image

JMP指令:在代码中改变程序运行的位置

示例:

  • 在代码中改变程序运行的位置为:0x20000(CS和IP一起改变)

    jmp 2000:0000	// cs设置为0x2000,IP设置为0x0000
    

    image

  • 只改变IP

    jmp 3	// 只设置IP为0x0003,CS不变
    

    image

利用JMP指令写一个死循环
使用a 2000:0 指令将代码写在地址0x20000处

在运行代码前将CS-IP设置为:2000:0000。

mov ax,00
inc ax
mov bx,ax
jmp 3

SS-SP:栈顶地址寄存器

栈的概念

先进后出

入栈:

image

出栈:

image

栈顶元素的地址

CPU要进行入栈和出栈的操作,就需要知道栈顶元素的地址,而SS-SP寄存器存放的就是栈顶元素的地址,其中SS为段地址,SP为偏移地址

设置SS-SP寄存器就是设置栈顶的地址

示例:设置栈顶地址为:0x10010

mov ax,1000
mov bx,0010
mov ss,ax		// 设置栈顶地址的段地址
mov sp,bx		// 设置栈顶地址的偏移地址

PUSH指令:入栈

注意:

  • 入栈时,栈顶从高地址向低地址增长

  • 栈操作都是以字为单位的,也就是16位数据

  • 每一次入栈SP都会减2,因为栈空间是16位的

  • 入栈时,高位先入栈,低位后入

  • 如果想将地址:0x10000~0x1000F作为栈空间,那么栈顶地址要设置为:0x10010。也就是栈顶地址比栈的起始地址大一,如下图

    image

示例:

// 设置栈顶地址
mov ax,1000
mov bx,0010
mov ss,ax		// 设置栈顶地址的段地址
mov sp,bx		// 设置栈顶地址的偏移地址

// 入栈
mov ax,0123
mov bx,2266
mov cx,1122
push ax		// 将ax中的值放到栈顶
push bx		// 将bx的值放到栈顶
push cx		// 将cx的值放到栈顶

使用d 1000:0000 F命令查看地址0x10000~0x1000F之间的数据

image

POP指令:出栈

沿用上面入栈代码运行后的栈空间、栈空间中的元素及栈顶地址

注意:

  • 每一次出栈SP都会加2
  • 栈操作都是以字为单位的,也就是16位数据

示例:

pop ax	// 取出栈顶的元素放到ax中
pop bx	// 取出栈顶的元素放到bx中
pop cx	// 取出栈顶的元素放到cx中

image

出栈入栈完整示意图

image

栈顶越界

8060没有记录栈顶上限和栈底的寄存器,需要我们使用时自己注意不要让栈越界

SI、DI、BX、BP:寻址

BX作为偏移地址

bx中的值也可以表示为偏移地址,如下

mov ax,1000
mov ds,ax		// 设置段地址为1000
mov bx,0010
mov ax,[bx]		// 把bx中的值当偏移地址,也就是将地址0x10010的值复制到ax中
mov cx,[bx+2]	// 把bx中的值加2后当做偏移地址
mov cx,[bx-5]	// 把bx中的值减5后当做偏移地址

注意:bx为偏移地址时,他的段地址在DS寄存器中

BP与BX的区别

BP与BX一样,都是作为偏移地址,也可以加减立即数

  • 只不过BX作为偏移地址时,段地址是DS寄存器中的值;
  • 而BP作为偏移地址时,段地址是SS寄存器中的值。也就是说BP操作的是栈

示例:

  1. 设置DS为:0x3000,SS为:0x1000

    image

  2. 运行如下代码

    mov ax,1234
    mov cx,6789
    mov bp,0000
    mov bx,0000
    mov [bp],ax		// 将ax的值放到地址0x10000处
    mov [bx],cx		// 将cx的值放到地址0x30000处
    
  3. 验证结果

    image

SI、DI与BX、BP

SI和DI有这与BX一模一样的作用和写法,可以单独使用,也可以加减立即数,默认段地址也是DS寄存器

与BX不同的是SI、DI可以单独与BX或BP相加,如下

mov ax,[si]
mov ax,[si+1]
mov ax,[di]
mov ax,[di+2]

mov ax,[bx+si]
mov ax,[bx+di]
mov ax,[bx+si+2]
mov ax,[bx+di+3]

// si或bi与bp相加后,默认段地址会变成ss
mov ax,[bp+si]
mov ax,[bp+di]
mov ax,[bp+si+1]
mov ax,[bp+di+4]

注意:si和di不能同时出现,以下写法都是错误的

mov ax,[si+bi]		// 错误的
mov ax,[bx+si+bi]	// 错误的
mov ax,[bp+si+bi]	// 错误的

寻址总结

其中:EA表示偏移地址;SA表示段地址;idata表示立即数

image

[bx].idata = [bx+idata]
idata[si] = [si+idata]
idata[di] = [di+idata]
[bx][idata] = [bx+idata]
[bx][si] = [bx+si]
[bx].idata[si] = [bx+idata+si]
idata[bx][si] = [bx+si+idata]

标志寄存器

概述

image

标志位寄存器在debug中的表现

标志位寄存器 值为1时的表现 值为0时的表现
OF OV NV
SF NG PL
ZF ZR NZ
PF PE PO
CF CY NC
DF DN UP

ZF:零标志位

作用:记录相关指令执行后,其结果是否为0。如果结果为0,那么zf = 1;如果结果不为0,那么zf = 0

示例:

mov ax,1	// 设置ax的值为1
dec ax		// ax自减1
inc ax		// ax自增1

image

PF:奇偶校验位

作用:相关指令执行后,其结果的所有位中1的个数是否为偶数。如果1的个数为偶数,pf=1;如果为奇数,那么pf=0。

示例:

mov ax,0	// 设置ax的值为0
inc ax		// 结果为:0x01,1的位数为奇数
dec ax		// 结果为:0x00,1的位数为偶数

image

SF:符号标志位

作用:记录相关指令执行后,其结果是否为负。如果结果为负,sf=1;如果非负,sf=0

计算机中表示正负数:

  • 最高位为0,表示这个数是正数。直接转化为十进制就是结果

  • 最高位为1,表示这个数是负数。对他按位取反后加一(也就是求补),转化为十进制后再加上负号就是结果

  • 对于同一个二进制,计算机可以将他当做无符号数据,也可以当做有符号数据

    例如:

    00000001B,可以看作为无符号数1,或有符号数+1

    10000001B,可以看作为无符号数129,也可以看作有符号数-127.

总结:SF标志,就是CPU对有符号数运算结果的一种记录,它记录数据的正负。在我们将数据当作有符号数来运算的时候,可以通过它来得知结果的正负。如果我们将数据当作无符号数来运算,SF的值则没有意义,虽然相关的指令影响了它的值。

示例:

mov al,3
sub al,5	// 3-5 = -2为负数
add al,10	// -2+16 = 14为正数

image

CF:进位标志位

作用:一般情况下,在进行无符号数运算的时候,它记录了运算结果的最高有效位向更高位的进位值,或从更高位的借位值。

image

示例:

  • 进位

    mov al,ff
    mov bl,22
    

    add al,bl // al+bl = 0x121,发生了进位

    
    ![image](/i/l/?n=24&i=blog/2742367/202411/2742367-20241125175053936-1802458390.png)
    
    
    
  • 借位

    mov al,01
    mov bl,02
    sub al,bl
    

    image

OF:溢出标志位

溢出的概念:在进行有符号数运算的时候,如结果超过了机器所能表示的范围称为溢出。

​ 例如:两个八位数98和99相加,其结果为197,显然该结果超过了8位有符号数可以表示的范围:-128~127。这就是相加溢出。相减的溢出也是同理

​ 如果在进行有符号数运算时发生了溢出,那么结果将不正确,如下:

98+99=197=0xC5。0xC5在计算机中用有符号数表示为-59,这结果显然是错误的

作用:由于在进行有符号数运算时,可能发生溢出而造成结果的错误。则CPU需要对指令执行后是否产生溢出进行记录。因此有了溢出标志位。一般情况下,OF记录了有符号数运算的结果是否发生了溢出。如果发生溢出,OF=1;如果没有,OF=0。

示例:

  • 相加溢出

    mov al,62	// 正数98
    mov bl,63	// 正数99
    add al,bl	// 0x62+0x63=0xC5;98+00=-59,发生了溢出
    

    image

  • 相减溢出

    mov al,f0	// -16的补码
    mov bl,78	// 正数120
    sub al,bl	// 0xf0-0x78=0x78;-16-120=120,这结果明显不对,发生溢出
    

    image

进位和溢出标志位的区别

CF和OF所表示的进位和溢出,是分别对无符号数有符号数运算而言的,它们之间没有任何关系。

image

基于标志位的运算

ADC指令:带进位的加法

image

作用:用来计算很大的数据

示例:

  • 计算:0x1EF000 + 0x201000,结果放到ax(高16位)和bx(低16位)中

    这两个数据都大于16位,用add指令无法直接计算。

    所以要将计算分为两步,先将低16位相加,然后再将高16位及进位值相加,如下

    mov ax,001e		// 将0x1EF000 的高位放到ax中
    mov bx,f000		// 将0x1EF000 的低位放到bx中
    add bx,1000		// 用add指令将低16位相加,他们产生的进位会记录到cf中
    adc ax,0020		// 用adc指令将高16位及进位值相加
    

    image

    adc指令执行后也可能会进位,也可以对cf进行设置。这样,我们就可以对任意大的数进行相加

  • 计算:0x1EF0001000 + 0x2010001EF0,结果放在ax(最高16位),bx(次高16位),cx(低 16 位)中。

    mov ax,001e
    mov bx,f000
    mov cx,1000
    add cx,1ef0	// 先将低16位相加,完成后,CF中记录本次相加的进位值
    adc bx,1000	// 再将次高16位和CF(来自低16位的进位值)相加,完成后,CF中记录本次相加的进位值
    adc ax,0020	// 最后高16位和CF(来自次高16位的进位值)相加,完成后,CF中记录本次相加的进位值
    

    image

    使用计算机验证:

    image

SDD指令:带借位的减法

image

作用:用来计算很大的数据

示例:计算:0x003E1000 - 0x00202000,结果放到ax和bx中

mov ax,003e
mov bx,1000
sub bx,2000
sbb ax,0020

image

使用计算机验证

image

CMP指令:比较指令

image

作用:比较两个数的大小。本质上cmp的功能相当于减法指令,只是不保存结果,cmp指令执行后,将对标志位寄存器产生影响。其他指令通过识别这些被影响的寄存器位来得知比较结果

  • 无符号数比较

    假设要比较的两个数存放在ax和bx中,执行指令:cmp ax,bx

    结果 标志位 描述
    ax = bx zf = 1 计算结果为0
    ax != bx zf = 0 计算结果不为0
    ax < bx cf = 1 计算结果产生借位
    ax >= bx cf = 0 计算结果没有借位
    ax > bx cf = 0 且 zf = 0 计算结果没有借位且不为0
    ax <= bx cf = 1 或 zf = 1 计算结果产生借位或结果为0
  • 有符号数比较

    结果 标志位
    ax = bx zf = 1
    ax != bx zf = 0
    ax < bx (sf = 1且 of = 0) 或 (sf = 0 且 of = 1)
    ax > bx sf = 1且 of = 1
    ax >= bx sf = 0 且 of = 0
    ax <= bx (sf = 1且 of = 0 或 zf = 1) 或 (sf = 0 且 of = 1或 zf = 1)

    逻辑如下:

    image

检测比较结果的条件转移指令

转移指的是能修改IP寄存器,而条件指的是可以根据某种条件,决定是否修改IP

image

示例:

如果ah = bh,则ah = ah+ah,否则ah = ah+bh

cmp ah,bh
je s			// 判断ah是否等于bh,如果等于,则跳转到标号s处执行指令
add ah,bh		// 如果不是,则执行该指令
jmp short ok	// 跳转到ok处执行指令
s:add ah,ah
ok:...

其他指令同上

汇编语言寄存器的英文全称中文对照表

16位寄存器

寄存器 英文全称 中文描述
AX(AL&AH) accumulator 累加寄存器
BX(BL&BH) base 基址寄存器
CX(CL&CH) count 计数寄存器
DX(DL&DH) data 数据寄存器
SP stack pointer 堆栈指针寄存器
BP base pointer 基址指针寄存器
SI source index 源变址寄存器
DI destination index 目的变址寄存器
IP instruction pointer 指令指针寄存器
CS code segment 代码段寄存器
DS data segment 数据段寄存器
SS stack segment 堆栈段寄存器
ES extra segment 附加段寄存器

标志位寄存器

寄存器 英文全称 中文描述
OF overflow flag 溢出标志位。溢出时为1
SF sign flag 符号标志位。为负时为1
ZF zero flag 零标志位。为0时为1
CF carry flag 进位标志位。进位或借位时为1
AF auxiliary carry flag 辅助进位标志位。第三位向第四位进位时为1
PF parity flag 奇偶标志位。1的位数为偶数时为1
DF direction flag 方向标志位。DF为1时,操作后使SI和DI减小,反之则增大
IF interrupt falg 中断标志位。为1时允许响应中断
TF trap flag 陷阱标志位。用于调试单步模式

标签:常用,16,mov,地址,寄存器,ax,bx
From: https://www.cnblogs.com/liuhousheng/p/18568276

相关文章

  • java基础day17:java8常用新特性
    一、Lambda表达式Lambda表达式就是匿名函数,匿名函数可以作为参数传递,表示数据。目的是让代码更加简洁,开发更高效!(参数1,参数2...)->{函数体}特点:​参数的类型可以不写,Lambda表达式可以根据上下文进行推断函数体如果只有一行代码,大括号可以不写。如果只有一行代码并是......
  • pg常用运维命令
    常用命令\d显示当前数据库中的所有的表、视图、sequence\dtest01显示test01表的详情\dt显示当前数据库中的所有的表\dttest*只列出test开头的表\db+查看pg中所有表空间\dn显示所有Schema\dv显示视图\di显示索引\ds显示序列号\df显示函数\du,\dg列出数据......
  • DB2数据库常用sql整理
    前言:        我们在查阅资料时,csdn上大部分数据库sql语句都是mysql或者oracle的,很难找到有关db2相关的sql,博主当年在修改db2数据库相关sql时曾经踩过很多坑,现在把以前整理过的sql语句整理到文章上供大家参考.    网上好多帖子写的db2相关的sql但凡放到......
  • 人大金仓常用命令(kingbase)
    背景项目常用的关系型数据库是mysql或者oracle,现在甲方很多都开始数据库国产化,而我们也跟着开始学习国产数据库的知识。通过架构部选型,暂定人大金仓作为mysql及oracle的平替。实验环境兼容mysql模式常用命令ksql----连接数据库的客户端,类似于mysql命令或者sqlplus命令。找......
  • Keil 5常用Debug功能及方法简述
    作为嵌入式工程师,学会使用Keil5的debug工具尤为重要,通过debug调试,开发者可以逐步跟踪程序的执行过程,观察变量的变化、寄存器的状态以及内存的使用情况,有助于开发者深入理解程序的内部机制,从而优化代码性能,提高程序的稳定性和可靠性。PS:(本文是综合原子的STM32F407探索者指南......
  • Linux常用命令之groupdel命令详解
    groupdel命令详解groupdel是一个用于删除用户组的命令行工具,常见于类Unix操作系统(如Linux和macOS)。通过groupdel命令,可以从系统中移除一个用户组。删除用户组时,需要注意一些重要的事项,以确保不会影响系统的正常运行。基本语法groupdel命令的基本语法如下:group......
  • Linux常用命令之chmod命令详解
    chmod命令详解chmod(changemode)是Unix和Linux操作系统中用于改变文件或目录的访问权限的命令。通过chmod,用户可以设置文件或目录的所有者、所属组以及其他用户(即非所有者且不属于文件所属组的用户)的读取、写入和执行权限。基本语法chmod命令的基本语法如下:chmod......
  • 深入解析 Java LinkedList:从基本特点到常用方法的全面介绍
    LinkedList是Java集合框架中非常常用的一种实现类,主要用于存储有序元素的链式结构。与ArrayList这种基于数组的实现不同,LinkedList使用双向链表来管理数据。在本文中,我们将从LinkedList的基本特点、继承关系、扩容机制、常用方法源码介绍、增删改查等多个方面详细解读......
  • docker-compose 配置文件内容详解以及常用命令介绍
    一、DockerCompose简介DockerCompose是一种用于定义和运行多容器Docker应用程序的工具。通过一个docker-compose.yml文件,您可以配置应用程序需要的所有服务(例如:Web服务器、数据库、缓存等)并轻松管理它们。Docker Compose使用的三个步骤:使用Dockerfile定义应用程序的......
  • HCIA-03 常用协议 ARP TCP UDP ICMP
    TCP/IP模型与OSI模型对比1.TCP/IP模型分为四层:应用层、传输层、网络层、数据链路层。2.OSI模型(开放系统互联模型)为七层:应用层、表示层、会话层、传输层、网络层、数据链路层、物理层。3.TCP/IP模型中的传输层对应OSI模型中的传输层和会话层,网络层对应OSI模型的网络层,数据链路层......