zoukankan      html  css  js  c++  java
  • 汇编

    在 win7 64位下学习汇编,无法使用 debug 和 masm,可以利用 DosBox 这个软件。

    DosBox 是一个 DOS 模拟程序,由于它采用的是 SDL 库,所以可以很方便的移植到其他的平台,支持 Windows、Linux、Mac OS X、Android 、webOS等系统。

    1、先下载好 debug 和 masm ,解压到 d:masm 目录下。

    2、运行 DOSBox 后,我们可以看到Z : >,这是 DOSBox 里的虚拟盘,使用 mount 命令将 d:masm 挂载到虚拟的 d 盘: mount d d:masm

    3、使用 "d:" 命令进入虚拟 d 盘,即可运行 debug 和 masm 程序。

    可以通过配置 dosbox-0.74.conf 文件(或者通过开始菜单中的 DosBox 0.74 -> Options -> DosBox 0.74 Options 找到),在打开的文本末尾会找到 [autoexec] ,在它之后加上:

    mount d d:masm
    set PATH=Z:;d: d:
    cd source

    这样就不需要每次进入 DosBox 都要重新配置了,并且设置了环境变量,可以在代码目录直接进行编译和链接了。

    radasm 是一款汇编语言的 IDE,很好用,但是只能在 32 位系统下运行。官网下载只是一个编辑器,不带编译汇编功能,可以从网上下载整合好OD、masm 的汉化版,安装好之后,如果配置下 masm 的环境变量,“选项"——>"环境变量"——>将 PATH 设置成如 C:RadASMmasm32in; 即可。

    linux 下可以使用 objdump 将二进制文件反汇编,如  objdump -d test1 

    Hello,World!

    windows 版:

    data    segment                ;数据段
    hello    db    'Hello,World!$',0
    data    ends
    
    code    segment                ;代码段
        assume    cs:code,ds:data
    start:                    ;入口
        mov    ax,data
        mov    ds,ax
        lea    dx,hello
        mov    ah,9h
        int    21h
        mov    ah,4ch
        int    21h
    
    code    ends
    
    end start            ;标志入口点

    linux 版:

    .section .data
    msg: .ascii "Hello,World!
    "
    len= . -msg
    
    .section .text
    #.globl main
    .globl _start
    #main:
    _start:
        movl $4,%eax
        movl $1,%ebx
        movl $msg,%ecx
        movl $len,%edx
        int $0x80
        movl $1,%eax
        movl $0,%ebx
        int $0x80

    使用 gcc hello.s 会编译错误,是因为用cc编译的话_start这个符号已经有定义了,这个是c runtime入口,cc编译的C程序的真正开始位置是_start symbol,这个_start在它初始化运行环境后调用main,因此你需要使用as编译这个汇编程序,因为gcc已经把_start占用了,如果非要用gcc可以使用gcc -nostdlib hello.s 编译, -nostdlib 让 gcc 不链接标准库。或者,把 _start 改成 main。

    debug 的常用命令:

    1、R: 寄存器显示与更改(Register)
    格式:R [寄存器]
    寄存器:AX BX CX DX SP BP SI DI DS ES CS IP PC F

    若R不带参数,则显示所有寄存器的内容和状态标志、下一指令。
    若指定新值,在显示内容后,给出冒句提示输入新值。回车结束。
    对状态字F,在连字符 - 后以空格间隔输入新值,次序不计。
    若直接回车,则跳过修改,寄存器内容不变。 

    2、D: 显示内存内容(Dump)
    格式:D [段地址:起始偏移地址] [结尾偏移地址]
    内存内容显示指令,以十六进制和ASCII码形式显示指定范围内的内存内容。
    若不指定范围,第一次按目标程序的 CS:IP 的位址开始显示显示 128byte 的内容,以后使用上次显示的未地址的下一地址为开始进行显示。

    3、E: 数据的输入(Entering)
    格式:E [段地址:起始偏移地址] 数值列表(可以是数字、字符、字符串、机器码,以空格隔开)
    向内存区域输入数据。数据以十六进制形式,或以ASCII码形式均可,覆盖掉原有数据。
    十六进制时要用空格、逗号或制表符加以分隔。字符串则要用单引号或双引号括起且区分大小写。
    若不指写段址,则默认为 DS 值,每写完一数据地址自动增加。
    如省略数值列表,可以提问的方式逐个修改从某一地址开始的内存单元中的内容,点号前为该字节原始值,点号后请求输入。这时若按空格,跳过这一字节,输入下一字节;按回车,结束输入;按减号或连字符,显示或修改前一字节内容。 字符串只能以数值列表的形式输入,不能按提问的方式输入。 

    4、U: 反汇编(Unassemble)
    格式:U [段地址:起始偏移地址] [结尾偏移地址]
    将机器指定解码为汇编语言的助记符,若地址范围中无段址时,默认使用CS值。若不含末地址或长度,则自给定始地址起反汇编32个字节。以后由前次U最后一指令的下一指令做32字节的反汇编。
    若从没用过U,则于CS:IP开始进行反汇编。
    只能对8086指令解码,对其它以DB来显示。 

    5、T: 程序执行跟踪(Trace)
    格式:T [=段地址:起始偏移地址] [指令数]
    没有 [指令数] 时,默认执行单条指令,显示寄存器及下一条指令。
    没有 [=段地址:起始偏移地址] 时,则默认为 CS:IP 寄存器的值。

    6、A: 编写汇编代码(Assemble)
    格式:A [段地址:起始偏移地址]
    用途:程序允许在指定位置(若无缺省为IP指针位置)进行汇编程序书写,相比于 E 命令写入机器指令要方便很多,使用方法也类似于 E 命令的提问方式。
    对内存地址加[]以与立即数区分。 

    栈:push pop

    任意时刻,SS:SP 指向栈顶元素。

    push ax ——> SP=SP-2 && mov SS:SP ax

    pop ax ——> mov ax SS:SP && SP=SP+2

    jmp short 标号

    jmp near ptr 标号

    jmp far ptr 标号:标号为四字节,前两个字节是IP(高位地址放高位,低位地址放低位),后两个字节是CS(高位地址放高位,低位地址放低位),不同于上面的,这里给出的是目标的 CS:IP 的绝对地址

    (CS)=标号所在段的段地址

    (IP)=标号所在段的偏移地址

    jmp word ptr 内存单元地址(段内转移):跳转到 [内存单元地址] 中的值指定的地址,此处 [内存单元地址] 存放一个字。 

    jmp dword ptr 内存单元地址(段间转移):此处 [内存单元地址] 存放两个字,(CS)=(内存单元地址+2),(IP)=(内存单元地址)

    jcxz 标号:条件转移指令,都是短转移,对应的机器码中包含转移的位移,而不是目的地址。如果 cx 为 0,则转移到标号处执行,否则不跳转。当 (cx)=0 时,(IP)=(IP)+8 位位移。相当于 if( (cx)==0) jmp short 标号;

    loop 标号:(cx)--; if ( (cx) !=0) jmp short 标号

    call 和 jmp 的区别,只是多做了一步把当前地址入栈的操作。

    mul 与 div

    8位相乘:AX中

    16位相乘:高位放于DX中,你们放于AX中

    DOS下,一般合法程序都不会使用 0:200 ~ 0:2ff (00200h~002ffh)的 256 个字节空间,所以我们可以拿来学习。

    8个通用寄存器:

    AX (Accumulator)  累加寄存器,可分为 AH 和 AL,属于数据

    BX (Base)  基址寄存器,可分为 BH 和 BL

    CX (Counter)  计数寄存器,可分为 CH 和 CL

    DX (Data)  数据寄存器,可分为 DH 和 DL

    SP (Stack Pointer)  堆栈指针寄存器,用来指示栈顶的偏移地址

    BP (Base Pointer)  基址指针寄存器,与段寄存器 SS 联用,可作为堆栈区的一个基地址,以相对方式访问堆栈中的存储单元。

    SI (Source Index)  源变址寄存器,与段寄存器 DS 联用,用来确定数据段中某一存储单元的地址。

    DI (Destination Index)  目的变址寄存器,可与 DS、ES 联用,用来确定数据段或附加段中某一存储单元的地址。

    四个段寄存器:

    CS (Code Segment) 存放程序段首地址

    DS (Data Segment) 存放数据段首地址

    ES (Extra Segment) 存放数据段首地址

    SS (Stack Segment) 存放堆栈段首地址

    两个控制寄存器:

    IP

    FR

  • 相关阅读:
    LeetCode
    LeetCode
    Django ORM 查询
    The Usage of Pymongo
    MongoDB基操
    Django内置auth模块中login_required装饰器用于类视图的优雅方式
    Django Session配置
    Python虚拟环境
    遇见Flask-Script
    Git使用手册
  • 原文地址:https://www.cnblogs.com/tianyajuanke/p/3358975.html
Copyright © 2011-2022 走看看