汇编教程(新手向)

汇编教程(新手向)写在前面不知道你会不会因为汇编语言学不明白而感到头疼,我在这里准备了一份简单的教程(因为我也不是很懂),以C语言转汇编语言的方式进行举例讲解,希望对你有用一个汇编程序的固定格式还记不记得学C语言的第一个难题?背固定格式//每一个C程序都会有一个这样的固定格式#include<s

大家好,欢迎来到IT知识分享网。汇编教程(新手向)"

写在前面

不知道你会不会因为汇编语言学不明白而感到头疼,我在这里准备了一份简单的教程(因为我也不是很懂),以C语言转汇编语言的方式进行举例讲解,希望对你有用

一个汇编程序的固定格式

还记不记得学C语言的第一个难题 ? 背固定格式

//每一个C程序都会有一个这样的固定格式
#include <stdio.h>
//我们定义的全局变量放在这里
int main(){
    //我们的程序代码放到这里
    return 0;
}

汇编语言也有自己的固定格式,每一次在编写一个汇编语言的时候都要讲固定格式写出

DATA SEGMENT

DATA ENDS

STACKS SEGMENT

STACKS ENDS

CODES SEGMENT
    ASSUME CS:CODES, DS:DATA, SS:STACKS 
START:
    MOV AX, DATA
    MOV DS, AX
    
    MOV AH, 4CH
    INT 21H
CODES ENDS
END START

如何快速的记忆汇编语言的固定格式呢

你这样来看

我们先去除 CODES 中那些繁杂的内容 代码就变成了这个样子

;注意哦,汇编语言的注释是以 ; 开头的

DATA SEGMENT

;这里是数据段

;在数据段里面我们放入自定义的变量、数组

DATA ENDS

STACKS SEGMENT

;这里是堆栈段

;在这里放入堆栈段的代码

STACKS ENDS

CODES SEGMENT

;这里是代码段

;在这里我们书写自己的代码

CODES ENDS

是不是这样就一目了然了呐,下一步我们来仔细看看CODES SEGMENT 里面的内容

ASSUME CS:CODES, DS:DATA,SS:STACKS  ;这句话的意思可以理解为 告诉程序,我们要用的段(代码,数据,堆栈)的位置在哪里

START :     ;这里不必过多解释啦 就是开始
    MOV AX,DATA
    MOV DS,AX 
    ; 上面这两句话看上去似乎很迷惑,总的作用不就是将DATA送给了DS嘛,为什么非要以AX做桥梁?
    ; 我在网上翻了很久,摆烂的告诉我:这是软件语言的规定,汇编就是要这样写,你记住就行!
    ; 也有人告诉我 段寄存器都要这样,不可以直接对它进行赋值,DATA就像一个立即数,不可以直接送入段寄存器的,一定要先给寄存器,再由寄存器交给 DS (听上去蛮靠谱的...)

    MOV AH,4CH
    INT 21H
    ;这两句话蛮重要的,AH是个了不得的寄存器,它和 INT是很好的朋友,在接下来的学习中,你会经常看到它们同时出现
    ;正经一点的解释是这样的 : 在 MOV AH,4CH 这句话中 AH 的值被赋值为 十六进制数 4CH 如果你有做微机系统的历年题的话,对INT 21H也许就不会陌生,DOS的系统调用嘛
    ;在系统执行INT 21H 进入系统调用后,就会去看 AH 的值,一看发现AH的值是 4CH ! 再去查查表,喔 ~ 是带返回码的结束的意思,这样就知道程序已经运行完毕啦

END START;在这里结束,不过要注意它的位置哦 ,这小子在 CODES SEGMENT 外面

汇编语言的 scanf() printf()语句

在这里就要使用到数据段DATA啦

DATA SEGMENT 
    Indata db ? ;我在这定义了一个名字叫做Indata的数据,它的大小是一个字节(咋看出来的?  db   b = byte )
    ;Indata dw ? 这样就是定义两个字节 (一个字)的变量了  后面加上一个问号,表示我们并不想给它赋初值
DATA ENDS

STACKS SEGMENT

STACKS ENDS

CODES SEGMENT
    ASSUME CS:CODES,DS:DATA,SS:STACKS
START :
    MOV AX,DATA
    MOV DS,AX

    ;上下都是固定格式,我们在这里开始写代码

    MOV AH,1
    INT 21H ; 你看这两个好兄弟又出现了,这次与上次有什么不同?是不是送往AH的数据不一样啊,当系统调用发现AH是 1 的时候,就知道程序是想要外界输入数据了
    MOV Indata,AL ; 输入的数据存储在AX寄存器中,我们定义的是一个字节,所以只需要读 低8位即可,如果是一个字的话,就要读整个AX寄存器
    
    ;好啦,到了这里我们已经完成了数据的读入,并将它放在了Indata里面,下面我们把它输出出来

    MOV DL,0AH
    MOV AH,2
    INT 21H 
    ; 哦吼又换了一个数,AH 中是 2 ,系统就知道是想要往外输出数据了,那么输出的数据是什么嘞? 就是DX寄存器中的内容,我们只用的到低8位,所以上面写的是DL
    ; 那他会输出什么呢 ? DL寄存器中存储的 0AH 其实是换行符的ASCLL码值 这句话会输出一个换行啦
    
    ;如法炮制,完成Indata的输出
    MOV DL,Indata
    MOV AH,2
    INT 21H

    MOV AH,4CH
    INT 21H
CODES ENDS
END START

汇编语言中的分支语句

DATA SEGMENT 
    Indata db 00000001B ;这里我给了它初值,二进制末尾是B 不加是十进制 十六进制是H
DATA ENDS

STACKS SEGMENT

STACKS ENDS

CODES SEGMENT
    ASSUME CS:CODES,DS:DATA,SS:STACKS
START :
    MOV AX,DATA
    MOV DS,AX

    mov al, 1
    
    cmp al,Indata
    ;cmp 指令其实是一个相减的指令,如果结果等于 0  的话表示相等 不过它不会改变操作数的值,它改变的是标志寄存器的值
    ;状态标志位: ZF 零标志,当运算结果为  0  的时候置 1 
    ; SF 符号标志 是有符号数的最高位的值 所以为 1 的时候是负值 为 0 的时候是正值


    jz deIndata ;JZ的意思就是 jump zero 当ZF标志位为 1 的时候执行跳转

adIndata: inc Indata ;执行跳转之后这句话就会被略过了 (indata ++)

deIndata: dec Indata ;直接执行这句话 indata --

    MOV DL,Indata
    MOV AH,2
    INT 21H

    MOV AH,4CH
    INT 21H
CODES ENDS
END START

还有一些分支跳转指令可以记一下

  1. 比较两个数相等的 :

    JE label ;这个和JZ一样的,相等跳转

    JZ label ;

  2. 左边小于右边 :

    JL label 小于则跳转

    JNGE label 和上面的一样 not greater or equal

    JB label; Jump if Below 低于、不高于或等于 (CF寄存器为 1 )

    JNAE label;Jump if Not Above or Equal

  3. 左边小于等于右边 :

    JLE label;小于等于

    JNG label;不大于

  4. 左边大于右边:

    JG label;大于

    JNLE label;不小于等于

  5. 左边大于等于右边:

    JNL label;大于等于

    JGE label;

    JNB label;Jump if not Below 不低于、高于或等于

    JAE label;Jump if Above or Equal

帮助记忆区分 如果是无符号数运算的话 用 above 和 below 如果是有符号数运算的话用 less 和 greater

还有一些其他的:
JC label ;运算结果有进位跳转
JNC label
JO label ;运算结果有溢出跳转
JNO label;
JS label;运算结果为负跳转(SF标志寄存器)
JNS label
JP label; 低8位中 1 的个数为偶数(PF标志寄存器)
JPE label; jump if parity Even 为偶数跳转
JNP label; 为奇数跳转
JPO label;Odd 为奇数跳转

汇编语言中的循环语句

假设情形 : for(int i = 0 ;i <= 4 ;i++)

如何用汇编语言来表达这件事情嘞 ?

有两种方式 :

  1. 自动绑定 CX 寄存器的LOOP语句
mov cx,4
next :  ... ;这里写自己的循环体
        loop next; 这样他会自动的将 cx 中的值减一 然后再回到 next 指向的地方
  1. 我自己来决定什么时侯结束的类 break 语句
mov cx,4 ;这个就不是一定需要使用 cx 寄存器了,但是上面的 LOOP 是要使用的哦
next:   ...
        dec cx; cx --
        jnz next; 如果上一步运算的结果不是 0 的话就继续

举一个再大一点的例子叭 : 统计 01 的个数

data segment
    InData dw 1001100110000011B; 一个字的数据 两个字节 16位喔
    num0   db ?; 这就是 一个字节 8 位
    num1   db ?
data ends

code segment
          assume cs:code, ds:data
    start:mov    ax,data
          mov    ds,ax

          mov    ax,InData   

          mov    cx,16  ;使用loop之前先告诉它要循环多少次

          mov    bl,0                          ;存0
          mov    bh,0                          ;存1

          ;进入循环之前可能先要说一下test语句 : 按位与  和 CMP 一样改变的是标志位的值                         
    next: test   ax,1         ; ax & 1   zf=1 add0  zf=0 add1      如果最后一位不是 1 的话 跳转add0 
          jz     add0         ; if zf = 1 jmp
          inc    bh           ;如果没有经过跳转会来到这里 ++bh
          jmp    over         ;然后去 over 那里移位
    
    add0: inc    bl           ;这部执行完之后也会向下进入over 
    
    over: shr    ax,1 ;右移

          loop   next         ; cx = cx - 1, if cx != 0 jmp  

          mov    num0,bl
          mov    num1,bh

          mov    ah,4ch
          int    21h

code ends
end start

;这些用来输出最后的结果
;mov    dl,num0
;add    dl,48
;mov    ah,2
;int    21h
;mov    dl,32
;mov    ah,2
;int    21h
;mov    dl,num1
;add    dl,48
;mov    ah,2
;int    21h

差不多就是这样啦,如果还有补充的,等我学完再来告诉你..

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/30488.html

(0)

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

关注微信