【汇编要笑着学】汇编模块化编程 | call和ret调用指令 | jmp跳转指令 | inc自加指令

Ⅰ.汇编模块化编程

0x00 一个简单的例子

我们了解模块化编程前先给出一个例子,方便大家快速了解。

SECTION MBR vstart=0x7c00 ; 起始地址编译在0x7c00
    mov ax,cs             
    mov ds,ax             
    mov es,ax
    mov ss,ax
    mov fs,ax
    mov sp,0x7c00   ; 上面这些都没什么用,但是都是必须的
                    ; 就把这些理解为初始化吧    

    call main

    jmp $

eax_plus_1s:
    inc eax
    ret

ebx_plus_1s:
    inc ebx
    ret

main:
    mov eax, 0
    mov ebx, 0
    call eax_plus_1s
    call eax_plus_1s
    call ebx_plus_1s
    add eax, ebx
    ret

times 510 - ($ - $$) db 0 
db 0x55,0xaa

这段代码用到了了我们今天要学的所有知识。

我们用bochs运行一下。

什么?这次几天,你就忘了?

算了,重新发一下命令。

nasm -o a.bin a.S
dd if=a.bin of=hd60M.img bs=512 count=1 conv=notrunc
bochsdbg -f bochsrc

输入c运行等一会后,再输入r命令查看寄存器数据。

得到结果3。

 

这段代码实际上看意思应该就大概知道了。

0x01 代码段

首先我们讲讲代码段,也就是上面代码中的。

main:
    ...

格式如下:

代码段名:
    代码段

 或者

代码段名称: 代码

代码段中的本质到底是什么呢?

我们可以大胆猜测一下,有如下可能:

  • 类似c语言中的函数
  • 类似c语言中的标签

我们可以把这个存入ax看一下试试。

SECTION MBR vstart=0x7c00 ; 起始地址编译在0x7c00
    mov ax,cs             
    mov ds,ax             
    mov es,ax
    mov ss,ax
    mov fs,ax
    mov sp,0x7c00   ; 上面这些都没什么用,但是都是必须的
                    ; 就把这些理解为初始化吧    

    mov ax, main

    jmp $
    
    times 510 - ($ - $$) db 0 
    db 0x55,0xaa

运行试试。

7c18应该就是一个地址,那就和c语言的标签类似。

call指令就是调用代码段,和函数调用差不多。

jmp就和c语言的goto差不多。

里面的

jmp $

就是原地循环,$就是当前指令的地址。

ret指令和return差不多。

Ⅱ.call和ret调用指令

0x00 call指令语法

call指令语法很简单:

call 标号

功能如下:

  call指令可以实现调用一个子程序,在子程序里使用ret指令结束子程序的执行并返回主程序(类比C语言中的main函数调用cube函数进行理解),主程序继续往下执行。

0x01 call指令本质

call指令是一个流程转移指令,就是让程序执行的顺序发生短暂的改变,去执行别处地址上的指令,遇到ret指令后再回到原来的地方继续往下顺序执行,本质和jmp大同小异,区别是在jmp基础上增加了程序回到原来跳转处的功能。

执行的指令如下:

  • 第一步:将当前的ip或者cs和ip压入栈中。即跳转前保存call指令的下一条指令的首地址
  • 第二步:转移到标号处执行子程序。即修改ip或者cs和ip里的内容

例子?懒得写了

Ⅲ.jmp跳转指令

0x00 什么是jmp指令

接下来就是jmp指令了!

感觉今天这篇怪水的...

cpu要执行指令之前必须先取指(把指令从内存传输到cpu中),从而必须要给出指令所在内存单元的物理地址,寄存器cs:ip就是这个物理地址所对应的段地址和偏移地址(段地址16+偏移地址=物理地址*),而jmp指令就是用来修改ip或者cs和ip的内容,使cpu执行jmp所指向的那条指令(发生跳转/转移),不会执行原定顺序的下一条指令。所以jmp指令要给出两个信息,如下:
jmp指令要给出两种信息:

  1. 转移的目的地址
  2. 转移的距离/偏移地址(距离不同转移的类型不同)
  • 段间转移(远转移):同时修改cs和ip
  •    段内短转移:jmp short 标号 ;只修改ip的值,ip的修改范围为-128~127(负数跳转方向是jmp指令之前,否则是之后),8位的位移
  •   段内近转移:jmp near ptr 标号 ;只修改ip的值,ip的修改范围为-32768~32767,16位的位移

0x01 jmp指令格式

备注:在源程序中,不能直接使用“jmp 2000:0100"这样的转移指令来实现段间转移,这种方式在debug模式中使用的汇编指令,在源程序中写,编译器并不识别(编译报错)

懒得写了,截的别人的图。

例子?懒得写了

我们这个都是按照上面图片讲的,例子都没有。

Ⅳ.inc自加指令

这个指令应该是我们这节课最简单的一个指令了。

0x00 inc指令是什么

inc指令差不多相当于c语言中的++一样,不过没有先后一说。

也就是

inc ax

相当于汇编中的

add ax, 1

这也太tm简单了,我就不再讲了。

        总结:
        这节课主要讲的就是汇编模块化编程,还有一个自加指令。
        还是很简单的。

        最后建议大家还是自己多试试,不要只看:
        纸上得来终觉浅,绝知此事要躬行。

  • 23
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值