68000汇编实战01-编程基础
文章目录
- 简介
- 产生背景
- 应用领域
- 语言学习
- EASy68K
- 帮助文档
- IDE使用
- 编程语言
- comments
- labels
- 开始标签
- 指令标签
- 位置标签
- opcode 操作码
- 常用操作码
- 数据传送
- 算术运算
- 逻辑运算
- 控制流
- 分支跳转
- 地址跳转
- 子程序跳转
- 位操作
- 比较
- 堆栈操作
- IO操作码
- 其他操作码
- directives 指令
- DC指令
- EQU 指令
- SET 指令
- DS 指令
- 其他指令
- 寄存器
- 程序计数器(PC)
- 状态寄存器(SR)
- 状态寄存器的结构
- 状态寄存器的作用
- 示例
- 数据寄存器(D)
- D 寄存器的特点
- D 寄存器的使用场景
- 示例
- 地址寄存器(A)
- A 寄存器的特点
- A 寄存器的使用场景
- 示例
- 堆栈寄存器(SS)
- 堆栈操作
- std函数模拟
- 案例(9*9乘法表)
简介
68000 汇编语言是为 Motorola 68000 微处理器设计的低级编程语言。68000 微处理器于 1979 年推出,因其强大的性能和灵活的架构而广泛应用于多种计算机系统和嵌入式设备中。以下是对 68000 汇编语言的背景、应用领域以及学习它的好处的详细介绍。
产生背景
-
技术进步:
- 68000 微处理器是 16 位架构,具有 32 位的地址总线,能够寻址高达 4GB 的内存。这使得它在当时的微处理器中具有较高的性能和灵活性。
- 其设计采用了复杂指令集计算(CISC)架构,支持多种寻址模式和丰富的指令集。
-
市场需求:
- 1970 年代末和1980年代初,个人计算机和嵌入式系统的需求迅速增长。68000 微处理器因其性能和成本效益被广泛采用。
- 许多知名的计算机系统(如 Apple Macintosh、Atari ST 和 Sega Genesis)都使用了 68000 处理器。
应用领域
-
个人计算机:
- 68000 微处理器被用于早期的个人计算机,如 Apple Macintosh 和 Atari ST。这些系统的操作系统和应用程序通常使用 68000 汇编语言进行开发。
-
嵌入式系统:
- 68000 处理器也被广泛应用于嵌入式系统,如工业控制、汽车电子和消费电子产品。
-
游戏机:
- Sega Genesis 和其他游戏机使用 68000 处理器,许多经典游戏都是用 68000 汇编语言编写的,学习后可以做一些hackrom的实战。
-
实时系统:
- 由于其高效的性能,68000 处理器在实时系统中也得到了应用,如医疗设备和航空航天系统。
语言学习
EASy68K
EASy68K 是一个 68000 结构化汇编语言集成开发环境(IDE)。EASy68K 允许您在 Windows PC 或 Wine 上编辑、汇编和运行 68000 程序。无需额外的硬件。EASy68K 是一个开源项目,根据 GNU 通用公共使用许可分发。
使用easy68k方便我们学习整套68000的编程和调试,学习这件基础知识,对我们hackrom或者逆向的基础。
下载地址:http://www.easy68k.com/files/SetupEASy68K.exe
安装完成后的目录结构
帮助文档
helm.chm提供了完整的编程和调试工具以及68k语言的学习入门资料,可以直接从该文档入手。
IDE使用
打开EDIT68K.exe,菜单file->new x68 source file 。
在source里面实现一个功能,打印helloworld,并从空值台输入一个字符串并打印。
关于指令,标签,寄存器其他相关的内容请移步后续章节。
源代码
*-----------------------------------------------------------
* Title :
* Written by :
* Date :
* Description:
*-----------------------------------------------------------ORG $1000 ;告诉编译器代码从1000位置开始,不指定默认从0开始
START: ; first instruction of program* 将text字符串地址写给A1lea text,A1* 将14号task print 给d0,并执行,14号任务自动获取A1地址的数据并打印move #14,D0trap #15* 执行2号任务,从输入流获取输入,自动写入到A1move #2,D0trap #15* 打印A1地址内容move #14,D0trap #15* Put program code here
*-----------------------------------------------------------
*HELLO:这是一个标签,标识字符串数据的起始位置。
*DC.B:这是一个伪指令,表示“定义常量(Define Constant)”,后面的 .B 表示定义的是字节(Byte)数据。
*'Hello World':这是一个字符串常量,表示字符数组。每个字符占用一个字节。
*$D:这是一个十六进制常量,表示一个字节的值。$D 的十进制值是 13,通常表示回车符(Carriage Return)。
*$A:这是一个十六进制常量,表示一个字节的值。$A 的十进制值是 10,通常表示换行符(Line Feed)。
*0:这是一个字节的值,表示字符串的结束符(null terminator),在 C 语言中常用来标识字符串的结束。
*-----------------------------------------------------------
text dc.b 'helloworld',0SIMHALT ; halt simulator* Put variables and constants hereEND START ; last line of source
点击工具栏运行按钮(如果由错误会有提示,根据情况修正)
会弹出一个确认框
点击execute
绿色圈圈点击变成红色可下断点,F9运行,F8 stepover,F7 stepinto,点击运行可调试。
在view可打开内存窗口,栈窗口等
编程语言
汇编语言程序由以下部分组成:
- labels 标签 - 用户创建的名称,用于标记程序中的位置。
- opcode 操作码 - 微处理器可以执行的特定指令,比如ADD,MOVE等。
- operands 操作数 - 某些指令所需的附加数据,比如#1表示10进制立即数1,$1表示16进制的1。
- directives 指令 - 发给汇编器的命令,比如ORG $1000,告诉编译器,代码的开始位置,代码段不占用空间,类似于c语言的宏,编译阶段使用。
- macros 宏 - 用户创建的源代码集合,可以在编写程序时轻松重用。
- comments 注释 - 用户创建的文本字符串,用于记录程序。
- 寄存器:汇编语言编程需要与微处理器进行直接交互。68000 微处理器包含八个数据寄存器 D0 到 D7。数据寄存器是通用的,可以视为 8 位、16 位或 32 位的整数变量。还有八个地址寄存器 A0 到 A7,地址寄存器的长度为 32 位。它们通常用于引用变量。状态寄存器(SR)包含状态标志,用于指示比较的结果。
以下是一个例子
comments
在 Motorola 68000(68k)汇编语言中,注释用于帮助程序员理解代码的功能和逻辑。68k 汇编语言的注释格式如下:(*或者;开头的为注释)
* Date
TRAP #15 ;将3任务执行,自动打印D1的内容
labels
标签用于通过名称标识程序中的位置或内存位置。需要位置的指令或指令可以使用标签来指示该位置。标签通常在行的第一列开始,必须以空格、制表符或冒号结束。如果使用冒号,它不会成为标签的一部分。如果标签没有在第一列开始,则必须以冒号结束。标签的前 32 个字符是有效的。标签有两种类型:全局标签和局部标签。
全局标签可以在程序的任何地方被引用。因此,全局标签必须是唯一的名称。全局标签应以字母开头,后面可以跟字母、数字或下划线。局部标签可以在程序中重复使用。局部标签必须以点 ‘.’ 开头,后面可以跟字母、数字或下划线。全局标签定义了局部标签的边界。当定义局部标签时,只有在遇到下一个全局标签之前,才能从局部标签上方或下方的代码中引用它。汇编器通过将局部标签名称附加到前面的全局标签并用冒号 ‘:’ 替换点来创建局部标签的唯一名称。结果名称的前 32 个字符是有效的。
开始标签
标签可以用来指定程序的起始位置。如果标签 START 指定了程序的起始位置,那么 END 指令的写法如下:
START: Start of programcodeEND START
指令标签
标签常常放在某个指令前用来表示,定义变量,标签指向存储数据的首地址。
DC - DC 指令指示汇编器将后续的值放入当前内存位置。该指令有三种形式:DC.B 用于字节数据,DC.W 用于字(16 位)数据,DC.L 用于长(32 位)数据。定义常量指令不应与 C++ 中声明常量混淆。
例如
ORG $1000 start of the data region
depart DC.B 'depart.wav',0 stores as a NULL terminated string in consecutive bytes DC.L $01234567 the value $01234567 is stored as a long wordDC.W 1,2 two words are stored as $0001 and $0002DC.L 1,2 two long words are stored as $00000001 and $00000002
depart 就是一个label是这块内存区域的首地址。
内存结果
00001000 64 65 70 61 72 74 2E 77 61 76 00
0000100C 01234567
00001010 0001 0002
00001014 00000001 00000002
其他关于指令标签的用法参考,也可以到指令章节:
位置标签
可以定义一些位置标签,当进行特殊操作时,可以通过控制流opcode跳转到位置标签
实现一个从0,end_index的循环打印
ORG $1000
START: ; first instruction of program* Put program code here
* 实现一个从0,end_index的循环打印move #1,D1
t:move #3,D0TRAP #15 ;将3任务执行,自动打印D1的内容add.b #1,d1 ;让d1+1CMP #end_index,d1 ;比较d1和end_index的值BNE t ;如果不相等继续跳转到t label执行SIMHALT ; halt simulator* Put variables and constants here
end_index equ 10END START ; last line of source
opcode 操作码
在 68K 汇编语言中,操作码(opcode)是指令的核心部分,定义了要执行的操作。以下是一些常用的 68K 操作码及其功能:
常用操作码
注意大部分操作码都可以添加结尾.W表示字(2个字节16位).L表示双字(4个字节32位),.B(1个字节8位)
数据传送
- `MOVE`:将数据从一个位置移动到另一个位置。- 例:`MOVE.W D0, D1`(将 D0 的值移动到 D1)
- `MOVEA`:将地址从一个位置移动到另一个位置。- 例:`MOVEA.L A0, A1`(将 A0 的地址移动到 A1)
算术运算
- `ADD`:将两个操作数相加。- 例:`ADD.W D0, D1`(将 D0 的值加到 D1)
- `SUB`:从一个操作数中减去另一个操作数。- 例:`SUB.W D1, D0`(从 D0 中减去 D1)
- `MULS`:有符号乘法。- 例:`MULS D0, D1`(将 D0 和 D1 相乘,结果存储在 D1)
- `DIVS`:有符号除法。- 例:`DIVS D0, D1`(将 D1 除以 D0,结果存储在 D1)
逻辑运算
- `AND`:按位与运算。- 例:`AND.W D0, D1`(D1 与 D0 按位与)
- `OR`:按位或运算。- 例:`OR.W D0, D1`(D1 与 D0 按位或)
- `EOR`:按位异或运算。- 例:`EOR.W D0, D1`(D1 与 D0 按位异或)
- `NOT`:按位取反。- 例:`NOT.W D0`(D0 的值取反)
控制流
常用如下:
- `BRA`:无条件跳转。- 例:`BRA label`(跳转到指定标签)
- `BEQ`:如果相等则跳转。- 例:`BEQ label`(如果零标志位被设置,则跳转)
- `BNE`:如果不相等则跳转。- 例:`BNE label`(如果零标志位未设置,则跳转)
- `JSR`:跳转到子程序。- 例:`JSR subroutine`(跳转到子程序并保存返回地址)
- `RTS`:从子程序返回。- 例:`RTS`(返回到调用子程序的地址)
分支跳转
该指令将在程序中引发分支,如果某些标志被设置。共有十五种检查标志的方法。每种方法都有一个由两个字母组成的符号,用于替换 “cc” 在 “Bcc” 中。
- BCC:分支如果进位标志清除 - 当 C 标志为 0 时分支。
- BCS:分支如果进位标志设置 - 当 C 标志为 1 时分支。
- BEQ:分支如果相等 - 当 Z 标志为 1 时分支。
- BNE:分支如果不相等 - 当 Z 标志为 0 时分支。
- BGE:分支如果大于或等于 - 当 N 和 V 相等时分支。
- BGT:分支如果大于 - 当 N 和 V 相等且 Z=0 时分支。
- BHI:分支如果高于 - 当 C 和 Z 都为 0 时分支。
- BLE:分支如果小于或等于 - 当 Z=1 或 N 和 V 不同时分支。
- BLS:分支如果小于或相同 - 当 C=1 或 Z=1 时分支。
- BLT:分支如果小于 - 当 N 和 V 不同时分支。
- BMI:分支如果负 - 当 N=1 时分支。
- BPL:分支如果正 - 当 N=0 时分支。
- BVC:分支如果溢出标志清除 - 当 V=0 时分支。
- BVS:分支如果溢出标志设置 - 当 V=1 时分支。
- BRA:无条件分支 - 始终分支。
上面这些opcode根据标志触发跳转,只能跳转到label,注意进入label后会往下执行,和函数调用不一样,函数调用会返回,继续执行之前代码的下一行,这个不会,是直接跳转过去不回来了。
例子:
ORG $1000
START: ; first instruction of program* Put program code here
input:move.b #4,d0TRAP #15CMP #0,d1BNE input ;如果不等于0跳转到input标签,继续让输入数字BEQ exit ;如果等于0直接退出labelexit:SIMHALT ; halt simulator* Put variables and constants hereEND START ; last line of source
地址跳转
JMP(跳转)用于将程序控制转移到一个有效地址。它实际上相当于 MOVE.L xxx, PC,因为它将程序计数器更改为一个有效地址(计算得出)。
注意JMP是无条件跳转,相对于B开头的跳转,他也支持 JMP label的语法,同时他也支持直接JMP 地址的跳转。
ORG $1000
START: ; first instruction of program* Put program code here
input:move.b #4,d0TRAP #15CMP #0,d1BNE input ;如果不等于0跳转到input标签,继续让输入数字BEQ exit ;如果等于0直接退出labelexit:LEA quit,a0 ;=0跳转到这里后,将quit的地址给到a0,JMP直接跳转到地址,相当于:move.l a0,PC(这是伪代码)JMP (a0) ;如果想跳转到a0的下一个地址,可以1(a0) 或者n(a0),当然也可以直接JMP quitquit:SIMHALT ; halt simulator* Put variables and constants hereEND START ; last line of source
子程序跳转
JSR/BSR(跳转到子例程)与 JMP(无条件跳转)类似,但在跳转之前,JSR 会将跳转指令后面的地址压入栈中,这样可以通过 RTS(返回子例程)指令返回,也就相当于调用函数,函数执行完了,执行代码的下一行。
BSR适合同一代码段里的label直接调用,是相对掉哟个,JSR适合指定一个绝对地址调用(比如JSR $5000) ,但是实际上两个可以互相替换,没啥区别。
ORG $1000
START: ; first instruction of program* Put program code here
input:JSR input_notion ;JSR执行完后会自动执行下一行代码,B开头的跳过去就不回来了move.b #4,d0TRAP #15CMP #0,d1BNE input ;如果不等于0跳转到input标签,继续让输入数字BEQ exit ;如果等于0直接退出
input_notion: ;屏幕上输出提示语MOVE #14,D0LEA INPUT_STR,A1TRAP #15RTS ;注意返回了会运行调用这个函数的下一行
confirm_exit *屏幕上输出确认提示语MOVE #14,D0LEA CONFIRM_STR,A1TRAP #15RTS
exit:JSR confirm_exitmove.b #4,d0TRAP #15CMP #0,d1BEQ quitBNE input
quit:SIMHALT ; halt simulator* Put variables and constants here
INPUT_STR: dc.b 'please input number(exit=0):',0
CONFIRM_STR: dc.b 'confirm exit(:exit=0,not=1):',0END START ; last line of source
效果
位操作
- `SHL`:左移。- 例:`SHL.W #1, D0`(D0 左移 1 位)
- `SHR`:右移。- 例:`SHR.W #1, D0`(D0 右移 1 位)
- `ROL`:循环左移。- 例:`ROL.W #1, D0`(D0 循环左移 1 位)
- `ROR`:循环右移。- 例:`ROR.W #1, D0`(D0 循环右移 1 位)
比较
- `CMP`:比较两个操作数。- 例:`CMP.W D0, D1`(比较 D0 和 D1 的值)
堆栈操作
- `PUSH`:将数据压入堆栈。- 例:`PUSH.W D0`(将 D0 的值压入堆栈)
- `POP`:从堆栈弹出数据。- 例:`POP.W D0`(从堆栈弹出值到 D0)
IO操作码
TRAP #15 被用于触发 I/O. 不同的io流任务存储在: D0.
参考chm:
常用的输入输出任务:
- 14: 将A1地址对应的字符串输出 以0结尾结束。
- 13:将A1地址对应的字符串输出 以0结尾结束,加上\r\n换行。
- 2: 从控制台获取一个字符串回车后存储在A1地址中 0结尾。
- 4:读取一个数字写入D1.L中。
例子
START ORG $1000 Program load address.move #14,D0 ;设置14号任务打印A1地址字符串lea text,A1 ;获text地址到A1trap #15 ;激活任务SIMHALT text dc.b 'Hello World',0 ;0表示字符串结束END START End of source with start address specified.
其他操作码
关于更加详情的指令参考chm
directives 指令
指令是汇编器需要遵循的指令。它们占据源代码行中的第二个字段,与指令操作码占据的位置相同,但指令并不是 68000 操作码。 “DC” 和 “DCB” 是唯一会导致数据被添加到输出文件中的指令。指令还可以用于控制宏的汇编、条件汇编和结构化语法。
在以下描述中,选项项用方括号 [] 表示。用斜体显示的项应替换为适当的语法。
Usage:
[label] directive[.size] [data,data,...]^ ^ ^\_________________\_________\_____ varies by directive
DC指令
- 全称:Define Constant(定义常量)
- 用途:用于定义并初始化数据常量。
DC
指令可以用于定义一个或多个初始值,这些值会被存储在程序的输出文件中。 - 内存分配:
DC
指令会在程序的内存中分配实际的存储空间,并将指定的值写入该空间。 - 示例:
使用语法:
Usage:
[label] DC.size data,data,...
例子:
VALUE1 DC 10 ; 定义常量 VALUE1,值为 10
VALUE2 DC 20, 30 ; 定义常量 VALUE2,值为 20 和 30
- 特性:
- 定义的值在程序运行时是不可更改的。
- 实际在内存中占用空间。
注意下面的代码修改地址的值是非法的,常量无法修改
START: ; first instruction of programlea usercount,A0move.b 20,(A0) ;修改A0地址的常量这是非法的。
* Put program code hereSIMHALT ; halt simulator* Put variables and constants hereORG $1200
usercount dc.b 10,20dc.w 23
EQU 指令
-
全称:Equate(等于)
-
用途:用于定义一个符号并将其与一个值关联。
EQU
定义的值在整个程序中是不可更改的,通常用于定义常量或符号地址,类似于c语言的#define在预编译将对应引用的地方替换为值。 -
内存分配:
EQU
不会在内存中分配实际的存储空间。它只是创建一个符号,所有使用该符号的地方都会被替换为其定义的值。 -
示例:
MAX_SIZE EQU 100 ; 定义常量 MAX_SIZE,值为 100
-
特性:
- 一旦定义,
EQU
的值不能被修改。 - 不占用内存空间,编译时进行替换
- 一旦定义,
ORG $1000 ; 程序起始地址
START: ; 将立即数 10 移动到 D0 寄存器; 定义常量
MAX_COUNT EQU 2 ; 定义 MAX_COUNT 为 100
START_VALUE EQU 1 ; 定义 START_VALUE 为 10MOVE.B #10, D0ADD.B #MAX_COUNT, D0 ; 将 MAX_COUNT (100) 加到 D0SUB.B #START_VALUE, D0 ; 将 START_VALUE (10) 从 D0 中减去SIMHALT ; 停止模拟器ORG $1200 ; 数据段起始地址END START
SET 指令
-
用途:用于定义一个符号并赋予一个初始值,但与
DC
不同的是,SET
定义的值是可更改的。SET
通常用于在程序运行时动态地改变值。 -
示例:
COUNT SET 0 ; 定义符号 COUNT,初始值为 0 COUNT SET COUNT + 1 ; 重新定义 COUNT,值为 COUNT + 1
-
内存分配:
SET
指令并不分配实际的存储空间来存储值,而是定义一个符号,允许在程序中动态地改变该符号的值。
DS 指令
-
全称:Define Space(定义空间)
-
用途:用于定义一块未初始化的内存空间。
DS
指令只分配内存,但不初始化这些内存的值,随时可改。 -
示例:
BUFFER DS 256 ; 定义一个大小为 256 字节的缓冲区
-
内存分配:
DS
指令会在输出文件中分配指定大小的内存空间,但这些空间的初始值是未定义的(通常是随机值或零,具体取决于系统)。
定义一个100字节的空间,可以理解为数组,将MULT_TABLE数字第一个位置设置为:12
ORG $1000
START: ; first instruction of program* Put program code heremove.B #0,D0LEA MULT_TABLE, A0MOVE.B #12,(A0, D0)SIMHALT ; halt simulatorORG $1200
* Put variables and constants hereMULT_TABLE: ; 乘法表的存储位置DS.B 10 * 10 ; 预留 10x10 的空间END START ; last line of source
其他指令
参考chm
寄存器
程序计数器(PC)
程序计数器(有时在不同的体系结构中也称为指令指针或指令地址寄存器)保存下一条将要执行的指令的内存地址。每当 CPU 执行一条指令时,PC 的值会自动更新,以指向下一条指令。
更新机制:在大多数情况下,PC 在指令执行后自动加一(或加上指令的长度),以指向下一条指令的地址。
编写一个简单程序 运行,默认会从start:的写一条语句开始,PC寄存器指向初始代码的地址(注意有效的代码时左侧绿色点点的,其他都是指令或者注释)
按下F8执行到下一条
我这里将usercount的地址指向A0 ,同时加了ORG $1200从1200这个地址写入。点击A0的地址可以查看内存:
状态寄存器(SR)
在 68k(Motorola 68000)架构中,状态寄存器(SR,Status Register)是一个重要的寄存器,用于存储处理器的状态信息和控制标志。状态寄存器的内容影响程序的执行流程,特别是在条件跳转和中断处理时。以下是对 68k 状态寄存器的详细介绍:
状态寄存器的结构
68k 的状态寄存器是一个 16 位的寄存器,包含多个标志位。主要的标志位包括:
-
N(Negative):
- 表示最近一次运算的结果是否为负数。
- 如果结果的最高位(符号位)为 1,则 N 标志被设置。
-
Z(Zero):
- 表示最近一次运算的结果是否为零。
- 如果结果为 0,则 Z 标志被设置。
-
V(Overflow):
- 表示最近一次运算是否发生了溢出。
- 溢出通常发生在有符号数运算中,当结果超出可表示的范围时,V 标志被设置。
-
C(Carry):
- 表示最近一次运算是否产生了进位或借位。
- 在加法运算中,如果产生了进位,C 标志被设置;在减法运算中,如果发生了借位,C 标志也会被设置。
-
I(Interrupt Mask):
- 这是一个 3 位的中断屏蔽位,控制中断的响应。
- I0、I1 和 I2 位用于设置中断优先级,值越大,响应的中断优先级越低。
-
T(Trace):
- 这是一个单个位,用于启用或禁用跟踪模式。
- 当 T 位被设置时,处理器将在每个指令执行后产生一个中断,适用于调试。
-
S(Supervisor):
- 这是一个单个位,指示当前处理器是否处于特权模式(超级用户模式)。
- 当 S 位被设置时,处理器处于超级用户模式,允许执行特权指令。
状态寄存器的作用
- 条件跳转: 状态寄存器中的标志位用于条件跳转指令(如
BEQ
、BNE
等),根据运算结果的状态决定程序的执行路径。 - 中断处理: 中断标志位控制中断的响应,允许或禁止特定级别的中断。
- 运算结果的状态: 通过检查 N、Z、V 和 C 标志,程序可以根据运算结果的状态做出相应的处理。
示例
以下是一个简单的示例,展示如何使用状态寄存器的标志位:
MOVE.L #5, D0 ; 将 5 加载到 D0MOVE.L #3, D1 ; 将 3 加载到 D1SUB.L D1, D0 ; D0 = D0 - D1,结果为 2; 检查 Z 标志BEQ zero_result ; 如果 Z 标志为 1,跳转到 zero_result; 检查 N 标志BPL positive_result ; 如果 N 标志为 0,跳转到 positive_resultzero_result:; 处理结果为零的情况; ...positive_result:; 处理结果为正的情况; ...
数据寄存器(D)
在 68000(68k)架构中,D 寄存器(数据寄存器)是用于存储数据和操作数的寄存器。68k 处理器有 8 个数据寄存器,分别为 D0 到 D7。
D 寄存器的特点
-
数量:
- 68k 处理器有 8 个数据寄存器,编号为 D0 到 D7。
-
大小:
- 每个 D 寄存器的大小为 32 位(4 字节),可以存储 32 位的整数或指针。
-
用途:
- D 寄存器主要用于存储运算的操作数、结果以及临时数据。它们在算术运算、逻辑运算、数据传输等操作中被广泛使用。
-
寻址模式:
- D 寄存器可以与多种寻址模式结合使用,支持直接寻址、间接寻址等方式,方便数据的访问和操作。
-
操作:
- D 寄存器可以参与各种指令的操作,如加法、减法、位运算等。指令可以直接对 D 寄存器进行操作,也可以将 D 寄存器的值存储到内存中或从内存中加载数据。
D 寄存器的使用场景
- 算术运算: D 寄存器用于存储参与运算的数值。
- 数据传输: 在数据传输指令中,D 寄存器可以作为源或目标。
- 函数参数: 在调用子程序时,D 寄存器常用于传递参数。
示例
以下是一个简单的汇编代码示例,展示如何使用 D 寄存器进行基本的算术运算:
MOVE.L #10, D0 ; 将 10 加载到 D0 寄存器MOVE.L #5, D1 ; 将 5 加载到 D1 寄存器ADD.L D1, D0 ; D0 = D0 + D1,D0 现在为 15
地址寄存器(A)
68000(68k)架构中,A 寄存器(地址寄存器)是用于存储内存地址的寄存器。68k 处理器有 8 个地址寄存器,分别为 A0 到 A7。以下是对 A 寄存器的详细描述:
A 寄存器的特点
-
数量:
- 68k 处理器有 8 个地址寄存器,编号为 A0 到 A7。
-
大小:
- 每个 A 寄存器的大小为 32 位(4 字节),可以存储 32 位的内存地址。
-
用途:
- A 寄存器主要用于存储内存地址,支持数据的加载和存储操作。它们在指令中用于指向数据或指令的内存位置。
-
寻址模式:
- A 寄存器可以与多种寻址模式结合使用,包括直接寻址、间接寻址、基址寻址和相对寻址等。这使得程序能够灵活地访问内存中的数据。
-
堆栈指针:
- A7 寄存器通常用作堆栈指针(SP),指向当前堆栈的顶部。堆栈用于存储函数调用的返回地址、局部变量等。
A 寄存器的使用场景
- 内存访问: A 寄存器用于指向数据在内存中的位置,支持数据的读取和写入。
- 函数调用: 在函数调用中,A 寄存器可以用于传递参数和返回地址。
- 堆栈管理: A7 寄存器作为堆栈指针,管理函数调用的堆栈帧。
示例
以下是一个简单的汇编代码示例,展示如何使用 A 寄存器进行内存操作:
LEA array, A0 ; 将数组的地址加载到 A0 寄存器MOVE.L (A0), D0 ; 从 A0 指向的地址加载数据到 D0 寄存器ADD.L #1, D0 ; D0 = D0 + 1MOVE.L D0, (A0) ; 将 D0 的值存储回 A0 指向的地址
堆栈寄存器(SS)
在68k架构中,堆栈寄存器是用于管理程序运行时的堆栈的关键组件。68k系列处理器使用一个专用的寄存器来指向当前堆栈的顶部,这个寄存器被称为堆栈指针(Stack Pointer)。
在68k架构中,堆栈指针寄存器通常是 A7(地址寄存器7),它指向当前堆栈的顶部。
堆栈是一个后进先出(LIFO)的数据结构,用于存储临时数据,如函数调用的返回地址、局部变量和中断处理程序的上下文。
堆栈操作
我们来看下堆栈指针的移动和数据写入逻辑。
在68k汇编语言中,-(A7) 和 (A7)+ 分别用于表示压栈和出栈操作。
执行代码
move.l #10,-(a7)
未执行前原始堆栈地址A7指向:01000000,没有任何数据
执行:move.l #10,-(a7)
执行:move.l #20,-(a7)
执行出栈:move.l (a7)+,d0
std函数模拟
我们知道c语言的std约定是:调用函数先压入执行代码的后一个位置,然后参数从右往左压入,在函数内部出栈从左(后入先出)往右获取参数,执行完成获取代码执行的位置,跳转。
我们来模拟这个过程:
假设函数:
public int add(int a,int b)
用98k模拟堆栈实现:
ORG $1000
START: ; first instruction of program* Put program code heremove.l #10,-(a7) #第二个参数压栈。move.l #20,-(a7) #第一个参数压栈。LEA *+12, A0 *计算下LEA占用4个字节,一直到move.l d0,d2是12个字节,*+12就是从PC当前位置+12个就是下一个执行代码的位置move.l a0,4(a7) *将下一个执行的地址压栈JMP addmove.l d0,d2SIMHALT ; halt simulatoradd:move.l (a7)+,a0 ;地址出栈move.l (a7)+,d0 ;第一个参数出栈move.l (a7)+,d1 ;第二个参数出栈add.l d1,d0JMP (a0)* Put variables and constants hereEND START ; last line of source
案例(9*9乘法表)
*-----------------------------------------------------------
* Title :
* Written by :
* Date :
* Description:
*-----------------------------------------------------------ORG $1000
START: ; first instruction of program* Put program code heremove.b #start_index,d2 ;行索引move.b #start_index,d3 ;列索引
row:jsr print_str_line ;到row的部分就添加一个换行,jsr调用子程序,子程序需要RTS返回add.b #1,d2 ;每运行一次+1move.b #start_index,d3cmp #end_index+1,d2 ;到达最后一行+1直接退出BEQ exitcol:add.b #1,d3move.b d2,d1jsr print_num ;打印行的数字lea tmp_str,a1move.b #'*',(a1) ;打印一个*jsr print_strmove.b d3,d1jsr print_num ;打印一个列的数字move.b #'=',(a1) jsr print_str ;打印一个=move.b #1,d4muls d2,d4muls d3,d4move.b d4,d1jsr print_num ;打印一个列的数字move.b #' ',(a1) jsr print_str ;打印一个空格cmp d3,d2BEQ rowBNE col
print_num:move.b #3,d0TRAP #15 RTS
print_str:move.b #0,1(a1) ;打印字符的结尾move.b #14,d0TRAP #15 RTS
print_str_line:move.b #0,(a1) ;打印字符的结尾move.b #13,d0TRAP #15 RTS
exit:SIMHALT ; halt simulator* Put variables and constants here
tmp_str ds.b 2
end_index equ 9
start_index equ 0END START ; last line of source
效果
相关文章:
68000汇编实战01-编程基础
文章目录 简介产生背景应用领域 语言学习EASy68K帮助文档IDE使用 编程语言commentslabels开始标签指令标签位置标签 opcode 操作码常用操作码数据传送算术运算逻辑运算控制流分支跳转地址跳转子程序跳转 位操作比较堆栈操作 IO操作码其他操作码 directives 指令DC指令EQU 指令S…...
你的网站真的安全吗?如何防止网站被攻击?
你的网站被黑客攻击过,很可能不止一次! 这可不是危言耸听。微软最近发布了《2024 年微软数字防御报告》,报告中写到:“Windows 用户每天面临超过 6 亿次网络犯罪和国家级别的攻击,涵盖了从勒索软件到网络钓鱼再到身份…...
UE5 材质编辑器CheapContrast 节点
在 Unreal Engine 材质编辑器中,CheapContrast 节点是一个非常实用的节点,主要用于对图像或纹理的 对比度 进行调整,且执行效率较高,适合在性能要求较高的场景中使用。 CheapContrast 节点的作用 CheapContrast 节点通过调整输入…...
健身房小程序服务渠道开展
健身不单单是锻炼身体、保持身材,也是一种社交方式,城市里门店不少,每家都有一定流量和老客,但仅靠传统线下拉客/自然流量前往和线上朋友圈、短视频发硬广等方式还不够。 商家需要找到更多潜在目标客户,而消费者也对门…...
Java基础面试题08:Java中Exception和Error有什么区别?
在Java中,Exception 和 Error 是异常处理体系的两大核心概念。要理解它们的区别和应用,咱们可以逐步剖析。 Exception和Error的基础区别 共同点: 两者都继承自 Throwable 类,只有 Throwable 类型的实例才能被 throw 或 catch。 区…...
什么是axios?怎么使用axios封装Ajax?
学习目标 什么是axios怎么使用axios封装Ajax该如何使用Axios 封装 XHR 请求 什么是axios Axios 是一个基于 Promise 的 HTTP 客户端,它可以在浏览器和 Node.js 环境中使用。Axios 提供了简单易用的 API,用于执行各种 HTTP 请求操作,如 GET、P…...
Web前端学习_CSS盒子模型
content padding border margin <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>CSS盒子模型</title><style></style> </head> <body> <div class"demo&quo…...
JAVA项目-------医院挂号系统
1,项目目的 1、科室管理:新增科室,删除科室(如果有医生在,则不能删除该科室),修改科室。 2、医生管理:录入医生信息,以及科室信息。修改医生信息(主要是修改…...
[工具分享] 根据Excel数据根据Word文档模板,批量创建生成Word文档并重命名,方便快速查找打印
前几天交楼的小姐姐要多份Word文档合同打印给客户,那么100份就需要修改100次 上面好多都是模板的制式文件,里面的部分数据都是要根据实际值来变动的, 那么有没有快速的方法来操作呢,还是只能一个个手动的改,又容易出…...
Redis的管道操作
在现代应用程序中,Redis作为一种高性能的内存数据库,被广泛用于缓存、消息队列、实时分析等场景。为了进一步提高Redis的性能,Redis提供了管道(Pipeline)操作,允许客户端将多个命令一次性发送到服务器&…...
IT监控 | Oracle云监控全解析
Oracle云(Oracle Cloud)是Oracle公司提供的云服务平台,涵盖了IaaS、PaaS、SaaS和DaaS,支持企业在云中构建、部署、集成和扩展应用,为企业提供了管理服务器、应用程序、存储、网络和数据中心的全面控制能力。 跟踪Oracle云基础设施的关键组件将…...
前端面试题-1(详解事件循环)
1.了解浏览器的进程模型 1.什么是进程? 程序运行需要有它自己专属的内存空间,可以把这块内存空间简单的理解为进程 每个应用至少有一个进程,进程之间相互独立,即使要通信,也需要双方同意。 2.什么是线程?…...
Redis(5):哨兵
一、作用和架构 1. 作用 在介绍哨兵之前,首先从宏观角度回顾一下Redis实现高可用相关的技术。它们包括:持久化、复制、哨兵和集群,其主要作用和解决的问题是: 1)持久化:持久化是最简单的高可用方法(有时甚…...
【人工智能】Transformers之Pipeline(二十五):图片特征抽取(image-feature-extraction)
目录 一、引言 二、图片特征抽取(image-feature-extraction) 2.1 概述 2.2 google/ViT 2.3 pipeline参数 2.3.1 pipeline对象实例化参数 2.3.2 pipeline对象使用参数 2.4 pipeline实战 2.5 模型排名 三、总结 一、引言 pi…...
podman 源码 5.3.1编译
1. 构建环境 在麒麟V10服务器操作系统上构建:Kylin-Server-V10-GFB-Release-2204-Build03-ARM64.iso。由于只是编译 podman 源码,没必要特地在物理机或服务上安装一个这样的操作系统,故采用在虚拟机里验证。 2. 安装依赖 参考资料…...
矩阵重新排列——rot90函数
通过 r o t 90 rot90 rot90函数可以将矩阵进行旋转 用法: r o t 90 ( a , k ) rot90(a,k) rot90(a,k)将矩阵 a a a按逆时针方向旋转 k 9 0 ∘ k\times90^\circ k90∘...
Leetcode 51 N Queens Leetcode N Queens II
题意 给定一个数字 n n n,形成n*n的棋盘,棋盘上放n个皇后,确保皇后之间不会相互吃(皇后可以直线吃,斜线吃) 链接 https://leetcode.com/problems/n-queens/description/ 思考 这道题只能暴力枚举所有的…...
0.查找命令
目录 🍉 find - 查找文件 🍇 grep 🍓 which 🍈locate 总结: 🍉 find - 查找文件 # 语法 # find [搜索范围] [选项] # 选项 # -name<查询方式> 按照指定的文件名查找模式查找文件 # …...
HarmonyOS-初级(一)
文章目录 初级核心技术理念函数的声明和使用类的声明和使用接口声明和使用声明式UI的特征 🏡作者主页:点击! 🤖HarmonyOS专栏:点击! ⏰️创作时间:2024年11月28日12点50分 初级 HAP可以分为静…...
Oracle 11gR2 坏块修复实例一则
背景 前段时间在 Oracle 11gR2 数据库中发现了坏块问题。环境是 64 位 Linux 平台。本文将详细介绍如何使用 DBMS_REPAIR 进行在线修复,当然也可以基于备份和 RMAN 的修复方法这里暂时不做介绍。 发现坏块 1. 从 alert.log 中发现错误 在 alert.log 文件中发现了…...
解决FinalShell 连接virtual box安装的Linux centos/7系统 一直让输入密码,输入什么密码都没用
问题描述: virtual box安装的Linux centos/7系统默认只允许ssh登录方式,需要配置允许账号密码登录 先登录root账号(一定要是root):初始密码为vagrant su 修改ssh配置文件: vi /etc/ssh/sshd_config 修改…...
华为E9000刀箱(HWE9000V2)服务器硬件监控指标解读
随着数据中心规模的不断扩大,服务器的稳定性和可靠性变得尤为重要。华为E9000刀箱(HWE9000V2)作为一款高性能的服务器设备,其硬件状态的实时监控对于保障业务的连续性和系统的稳定运行至关重要。 监控易作为一款专业的IT基础设施监…...
Python基础学习-12匿名函数lambda和map、filter
目录 1、匿名函数: lambda 2、Lambda的参数类型 3、map、 filter 4、本节总结 1、匿名函数: lambda 1)语法: lambda arg1, arg2, …, argN : expression using arg 2) lambda是一个表达式,而不是一个语…...
民安:助力提升城市安全水平
随着城市化进程的加速,平安城市的创建成为了社会治理的重要议题。为了解公众对平安城市创建的看法和评价,为提升城市安全水平提供参考,近期某市委托民安智库专业市场调查公司开展了一次安全感满意度调查。 本次调查围绕公共安全、个人安全、…...
Apache Zeppelin:一个基于Web的大数据可视化分析平台
今天给大家推荐一下 Apache Zeppelin,它是一个基于 Web 的交互式数据接入、数据分析、数据可视化以及协作文档 Notebook,类似于 Jupyter Notebook。 Apache Zeppelin 支持使用 SQL、Java、Scala、Python、R 等编程语言进行数据处理和分析,同时…...
「Qt Widget中文示例指南」如何为窗口实现流程布局?(二)
Qt 是目前最先进、最完整的跨平台C开发工具。它不仅完全实现了一次编写,所有平台无差别运行,更提供了几乎所有开发过程中需要用到的工具。如今,Qt已被运用于超过70个行业、数千家企业,支持数百万设备及应用。 本文将展示如何为不…...
【C语言篇】探索 C 语言结构体:从基础语法到数据组织的初体验
我的个人主页 我的专栏:C语言,希望能帮助到大家!!!点赞❤ 收藏❤ 目录 什么是结构体结构体的定义与使用结构体内存布局嵌套结构体与指针结构体数组的操作结构体与函数结构体内存对齐机制位域与结构体的结合动态内存分…...
linux下USB设备状态查询
linux下USB设备状态查询 linux下USB设备状态查询 在buildroot RK3568平台上调试USB视频采集时发现,USB设备经常性断开,为发现其断开的规律,编写脚本记录其断开的时间 linux下USB设备状态查询 #周期性查询 USB设备 cat > /usr/bin/usbenq…...
鼠标前进后退键改双击,键盘映射(AutoHotkey)
初衷: 1.大部分鼠标为不可自定义按键,可以自定义的又很贵。 鼠标左键是双击是很频类很高的操作,鼠标前进/后退按键个人感觉使用频率很低,因此把鼠标前进/后退改为双击还是很合适的。 2.有些短款的键盘没有Home或End键,…...
ubuntu服务器睡眠命令
在 Ubuntu 服务器中,通常不会启用系统睡眠(即 suspend)模式,因为服务器通常需要保持持续运行以提供服务。但如果你希望让 Ubuntu 服务器进入睡眠状态,你可以使用以下命令: 1. 让系统进入休眠(S…...
基督教网站做父母怎样教养孩子/外贸建站推广哪家好
参考来源:https://blog.csdn.net/brycegao321/article/details/78038272在存储字符串时, 可以使用char、varchar或者text类型, 那么具体使用场景呢?参考下面这个表结构:1、 char长度固定, 即每条数据占用等…...
威海微网站建设/清远seo
现在做项目都会使用框架,现在很常见的框架就是SSH(StrutsSpringMVCspringhibernate),SSM(Struts/springMVCSpringHibernate),而我最近做的项目itoo中,使用到框架为easyUISpringMVCEJBhibernate.做项目分层是为了更好的解耦,分层可以完全不用你框架就能够解决,为什么还不需要这么…...
b2b电子商务网站的主要类型/百度推广怎么优化排名
import cv2 import numpy as npcap cv2.VideoCapture(0)# set blue thresh 设置HSV中蓝色、天蓝色范围 lower_blue np.array([78,43,46]) upper_blue np.array([110,255,255])while(1):# get a frame and show 获取视频帧并转成HSV格式, 利用cvtColor()将BGR格式转成HSV格式…...
有了域名之后如何做网站/青岛网络优化费用
原标题:大一新生开学,父母需给配“电脑”吗?辅导员:这4个专业必须有文/晓梅妈妈聊育儿每一年高考成绩出来后,有人欢喜有人愁,毕竟不是每一个考上都能取得高分,考上一所重点大学,而对…...
花钱做网站注意些什么/吸引人的软文标题
自己擅长的,不是自己喜欢的,这种事很常见。明熹宗朱由校是狂热的木工活爱好者,爱因斯坦对小提琴比相对论还有信心,象棋大师杨官麟下的围棋比象棋多,围棋国手聂卫平打桥牌更是废寝忘食。 钱钟书在《窗》中有个调侃&…...
网站建设公司官方网站/杭州百度快照
2019独角兽企业重金招聘Python工程师标准>>> 看了红薯的文章,都说Percona-Server的性能不错,领导也要求我测试一下。 先安装Percona-Server,去官网自己下载最新的centos6对应的最新的rpm包。安装顺利 安装测试工具,安…...