街机模拟游戏逆向工程(HACKROM)教程:[2]68K汇编的一些规则

发布时间:2024年01月15日

指令中的符号(#,$,%)

在指令中,我们最常见到的符号有#和$。

这其中的"#"符号是告诉汇编程序,这个符号后面的数值为一个立即数,而不是一个偏移值或一个地址。立即数可以理解为"单纯的一个数值"。我们会在后面通过一些实例来更详细说明什么叫立即数。

而$符号是告诉汇编程序,这个符号后的数值为一个16进制数值;如果符号为%,那它后面的数值为一个2进制的数值;如果没有任何符号,它后面的数为一个10进制数值。

我们来看以下几条代码:

move.b #%00010000,d0
move.b #16,d0
move.b #$10,d0

上面这几条指令的意思是一样的,第一行是2进制数值(%),第二行是10进制数值,最后一行是16进制数值($)

我们可以用计算器来查看各个进制之间的换算

我们回到立即数的问题,我们用两行代码来进行测试,更详细地说明什么是立即数

move.b  #$10,d0
*这条指令将会把$10这个数值置入到d0寄存器。

move.b  $10,d0
*这条指令将会读取地址$10处的字节,然后把它复制到d0寄存器,如果$10位置的值是88,那么d0寄存器的值也会在这条指令执行后变成88。

我们先来测试第一个指令:

*-----------------------------------------------------------
* Title      :
* Written by :
* Date       :
* Description:
*-----------------------------------------------------------
    ORG    $1000
START:                  ; first instruction of program

* Put program code here
    move.b #$10,d0 

    SIMHALT             ; halt simulator

* Put variables and constants here

    END    START        ; last line of source

?运行后的结果


*-----------------------------------------------------------
* Title      :
* Written by :
* Date       :
* Description:
*-----------------------------------------------------------
    ORG    $1000
START:                  ; first instruction of program

* Put program code here
    move.b #$88,$10     *把$88立即数 置入 地址$10
    move.b $10,d0       *把$10地址的值 置入 D0寄存器

    SIMHALT             ; halt simulator

* Put variables and constants here

    END    START        ; last line of source

运行结果:

奇数地址

至些为止,我们尝试了几个指令的执行,在了解更多的指令之前,我们还需要了解一些比较重要的东西。

我们刚刚测试了从内存中读写的例子:

move.b $10,d0

我们可以在操作长度为单字节的情况下,用奇数地址对内存进行读写,比如:

move.b $11,d0

但很重要的是,我们如果在操作双字节或四字节长度时,不能对奇数地址进行读写,比如下面的代码是一个非法的例子:

move.w $11,d0

move.l $11,d0

该规则对所有指令适用,所以,我们需要保证,需要从奇数地址读写数据时,只能读写单字节长度的数据。

标签

标签由字母、数字和下划线组成,必须以下划线、@符号或字母开头。标签后面可以有可选的冒号。标准汇编语言约定使用以“@”开头的标签作为过程或函数的本地标签。与其他类型的标识符一样,标签不区分大小写。

标签可以在任何指令的前面,我们可以在很多指令中使用标签功能,最常见的是jmp之类的跳转指令,比如:

   ORG     $100
START:

	move.w	d0, d1
	add.w	d1, d1
	add.w	d1, d0
	jmp	    label
	add.w	d2, d3
	asr.w	#$04, d0

label:
	move.w	d0, d2 

    END    START

我们可以测试这段代码,我们可以看到代码中的label:就是一个标签,当执行jmp? label时,程序会把label:标签所在的地址传递到PC寄存器。

   ORG     $100
START:
    movea.l #label,a0
    
label:
    move.w  d0,d2

    END    START

在这段代码中,当执行movea.l? #label,a0时,程序会把label:向在的地址传递到a0寄存器。

ORG指令

该指令声明了在内存中加载后续指令和数据的位置。

    ORG     $100
START:
    move.b  d0,d1
    
    ORG     $200
    move.b  d2,d3
    END    START

?

我们可以看到,第一句move指令被保存在了地址$100,第二句move指令被保存在了地址$200。

dc指令

定义常量。DC指令将指定的数据或字符串放置在指令流中。也可以把字符定义到指令流中。

我们可以测试:

   ORG     $100
START:
    dc.b    'abcd'
    dc.b    $01 , $02 , $03 , $04
    dc.w    $1010 , $1234
    dc.l    $30303030

    END    START

我们可以看到,该指令会把操作数直接置入到指令流中,当操作数为字符串时,会把该字符的ASCII码对应的值置入指令流。

ds指令

该指令会声明一段空白的内存空间。声明空间的大小由操作数和操作长度决定。

   ORG     $100
START:
    ds.b    $10
    dc.l    $00010203 , $04050607, $08090a0b, $0c0d0e0f
    ds.w    $10
    dc.l    $00010203 , $04050607, $08090a0b, $0c0d0e0f
    ds.l    $10
    dc.l    $00010203 , $04050607, $08090a0b, $0c0d0e0f
    END    START

我们可以看到,三个ds的指令虽然操作数都相同,但操作长度不同,所以,声明的空间大小也不同。

nop指令

该指令在程序中不起任何作用,我们可以把他想象为一个空指令,在逆向研究中,我们常常会用到该指令来对程序进行一些测试。

nop指令固定是占用2个字节的存储空间,它经过编译器编译后生成的机器码为"4E71"。这个机器码我们会经常用到。

文章来源:https://blog.csdn.net/m0_50114967/article/details/135445800
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。