如何快速看懂汇编语言程序

如何快速看懂汇编语言程序,第1张

首先得了解汇编指令吧,其次得用机器的逻辑思考问题,明白其中的存储、累加、判断、转移等概念。

比如,1+2++100这样的问题,虽然我们可以给出公式计算,但机器并不知道,它只能知道,而且只能每次做一个加法,而且鉴于CPU的架构不能存所有的这些数值-如果这些数量不定的话更复杂,比如这些数是放在一个内存区域的,内存区域约定如下:第一个数表示总共有多少个数,后面是相应的数据,在这些数没有规律时是不能用公式的。

另外,许多CPU约定只有一个累加器(同时也是一个寄存器,假设它是寄存器AX),它允许从内存读一个数(MOV或者LD指令),只能进行内存数据加法(ADD [地址])。

于是我们只能这样,首先设置指针寄存器BX:

start: mov BX,#地址 ; 设置内存区域起始地址,保存在BX中

mov CX,[BX]; 取出总数到CX中,假设CX可以做简单递增或递减

dec CX ; 预减一次计数器,因为加法只需做CX-1次

inc BX

mov AX, [BX]; 取出数据

loop: inc BX ;递增BX,使之指向真实数据

ADD AX,[BX];用下一数据进行累加,并将结果保存在AX中

dec CX ;假定这个减法会影响标志位ZF

JNZ loop ;如果没有减到0就继续loop到这里之间的 *** 作

mov [BX], AX; 保存累加结果到数据区的尾部

HALT ; 停机

可以看出,上述代码并不能告诉我具体结果是多少,除非我们通过工具去访问这一内存区域,于是一个系统会设计出来专门让我们进行基本的输入输出,把计算机的内部情况甚至内存情况通过I/O口送出来,这些IO设备,比如键盘负责接收我们的机器指令(可以是汇编结果,也可以是高级语言产生的二进制指令和数据流),把结果输出到打印机或者CRT这样的输出设备上(通常映射为端口,IO PORT)。这就是BIOS完成的工作,如int 8负责时钟,int 10负责屏幕,int 16负责键盘等等。更进一步,可以进一步封装称DOS调用,如int 21负责基本的输入输出包括文件 *** 作等等。WINDOWS等 *** 作系统则通过驱动层进行多级抽象提供 *** 作界面给编程人员,编程人员再进一步封装出对话框或全屏文字菜单或流式(行式 *** 作) *** 作界面给最终用户。

data segment

INPUT db 'The ASCII code of $'

OUTPUT db ' is $'

msg db 0dh,0ah,'is 0DH $'

A db 0

data ends

code segment

start proc far

assume cs:code,ds:data

push ds

sub ax,ax

push ax

mov ax,data

mov ds,ax

AGAIN: MOV DX,OFFSET INPUT

MOV AH,9

INT 21H

MOV AH,1

INT 21H

cmp al,0dh

jz tj

MOV A,AL

MOV AH,9

MOV DX,OFFSET OUTPUT

INT 21H

mov bl,a

mov bh,0

call dispa;以十进制形式显示ASCII码

mov dl,0dh

mov ah,2

int 21h

mov dl,0ah

mov ah,2

int 21h

jmp again

tj:

lea dx,msg

mov ah,9

int 21h

mov ah,1

int 21h

ret

start endp

dispa proc near

mov cx,100d

call dec_div

mov cx,10d

call dec_div

mov cx,1d

call dec_div

ret

dec_div proc near

mov ax,bx

mov dx,0

div cx

mov bx,dx

mov dl,al

add dl,30h

mov ah,2

int 21h

ret

dec_div endp

dispa endp

code ends

end start

ORG 0000H

AJMP MAIN

ORG 0030H

MAIN: MOV SP,#0X80

LCALL CX

AJMP $

//返回值在R7中

CX:

MOV R0,#0X40

MOV R7,#0

CX1: MOV A,@R0

CJNE A,#0X01,CX2

MOV R7,#1

AJMP CX_OUT

CX2: INC R0

MOV A,R0

CJNE A,#0X7F+1,CX1

CX_OUT: RET

END

ORG 0000H

LJMP MAIN

ORG 0030H

MAIN:

MOV R0,#30H

MOV 20H,#0

LOOP:

MOV A,@R0

CJNE A,#13,LOOP1

SJMP LOOPE

LOOP1:

CJNE A,#'a',LOOP2

INC 20H

LOOP2:

INC R0

SJMP LOOP

LOOPE:

SJMP $

END

;在MASM 615下编译通过

data segment

msg1 db 'Input String1:$'

msg2 db 'Input String2:$'

msg3 db 'Found str2 in str1 at:$'

msg4 db 'str2 not in str1',0dh,0ah,'str1+str2=$'

str1 db 255;输入缓冲区大小

db ;实际输入的字符数

db 255 dup();存贮STRING1

str2 db 255

db

db 255 dup();存贮STRING2

Pos db 3 DUP('$');用来存位置对应的数字字符串(16进制形式),第一个字符位置为00H

data ends

sta segment stack

db 1024 dup(0)

sta ends

CRLF macro;输出回车换行符

mov ah,02h

mov dl,10

int 21h

mov ah,02h

mov dl,13

int 21h

endm

code segment

assume cs:code,ds:data,es:data,ss:sta

FindInStr proc far

;入口参数

;[bp+8]=string2的开始地址

;[bp+6]=string1的开始地址

;[bp-2]=string2的长度,字节

;[bp-4]=string1的长度,字节

;[bp-6]=string1位置变量,字

;[bp-8]=最大查找次数,字节

;出口:AL=如果STR2在STR1中,则为第一次匹配时的位置,如果没找到,则为0FFH

push bp

mov bp,sp

add sp,-8

cld

;局部变量初始化

mov si,[bp+8]

mov di,[bp+6]

mov [bp-6],di

mov al,[si-1]

mov [bp-2],al

mov al,[di-1]

mov [bp-4],al

sub al,[bp-2]

inc al

mov [bp-8],al

mov cl,[bp-8]

xor ch,ch

LP_CMP:

push cx

mov si,[bp+8]

mov di,[bp-6]

mov cl,[bp-2]

xor ch,ch

repe cmpsb

jne Next

mov ax,[bp-6]

sub ax,[bp+6]

jmp RetHere

Next:

inc byte ptr [bp-6]

pop cx

loop LP_CMP

mov al,0FFH

RetHere:

mov sp,bp

pop bp

ret 4

FindInStr endp

TRANBUFF proc far;转化16进制数字串,入口参数AL=位置

CLD

XOR AH,AH

MOV BL,16

DIV BL

LEA DI,Pos

CMP AL,0AH

JB L1

ADD AL,37H

JMP L2

L1:

ADD AL,30H

L2:

STOSB

MOV AL,AH

CMP AL,0AH

JB L3

ADD AL,37H

JMP L4

L3:

ADD AL,30H

L4:

STOSB

ret

TRANBUFF endp

start:

mov ax,data

mov ds,ax

mov es,ax

mov ah,09h

lea dx,msg1

int 21h;显示Input String1:

mov ah,0ah

lea dx,str1

int 21h;用户输入STRING1

CRLF

mov ah,09h

lea dx,msg2

int 21h;显示Input String2:

mov ah,0ah

lea dx,str2

int 21h;用户输入STRING2

CRLF

lea ax,str2+2

push ax

lea ax,str1+2

push ax

call FindInStr

cmp al,0FFH

jz NoMatch

call TRANBUFF

mov ah,09h

lea dx,msg3

int 21h

mov ah,09h

lea dx,Pos

int 21h;显示找到的位置

jmp DONE

NoMatch:

cld

lea si,str2+2

lea di,str1

add di,2

xor ax,ax

mov al,str1+1

add di,ax

xor ax,ax

mov al,str2+1

mov cx,ax

rep movsb

mov byte ptr [di],'$'

mov ah,09h

lea dx,msg4

int 21h

mov ah,09h

lea dx,str1+2

int 21h;显示str2连接到str1后合并的字符串

DONE:

mov ax,4c00h

int 21h

code ends

end start

首先创建一个工程:Create a new project -> ConsoleApplication -> 填上工程文件名和project路径 -> 调试器和编译器默认。

随便在工程里写点什么代码,比如下面的一个递归代码为例:

#include "stdioh"

#include "mathh"

int factorial(int n);

int main(void)

{

int n, rs;

printf("请输入斐波那契数n:");

scanf("%d",&n);

rs = factorial(n);

printf("%d \n", rs);

return 0;

}

// 递归

int factorial(int n)

{

if(n <= 2)

{

return 1;

}

else

{

return factorial(n-1) + factorial(n-2);

}

}

点击“菜单栏 Debug -> Debugging windows -> disassembly”,把汇编窗口呼出来。

设定断点。就是设置查看汇编的那一段代码。在代码的左边(代码行)右键就可以设定调试断点了。

点击调试,就可以看到汇编代码了。如下:

如果想看指针或数组,可以编辑watch窗口,定义你想watch变量的类型。有很多窗口,自己可以多探索尝试。

以上就是关于如何快速看懂汇编语言程序全部的内容,包括:如何快速看懂汇编语言程序、汇编:编写ASCII码的查询程序、80c51单片机中,写一段汇编程序 在40H~7FH 中查找 一个数01H 若存在等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/zz/9848082.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-02
下一篇2023-05-02

发表评论

登录后才能评论

评论列表(0条)

    保存