第一个汇编程序

第一个汇编程序

1.0 一个源程序写出执行的过程

  • 编写-->编译masm-->链接link-->执行

1.1 执行可执行文件

  • 操作系统依照可执行文件的描述信息,将可执行文件加载到内存中,并进行相关的初始化参数(比如:设置CS:IP的值指向第一条要执行的指令),然后由CPU执行程序

1.2 源程序

  • 汇编指令 有对应的机器码指令,可以被编译为机器指令,最终被CPU执行

  • 伪指令 没有对应的机器码指令,伪指令是由编译器来执行的指令,编译器根据伪指令进行相关的编译操作

  • segment和ends是一对使用的伪指令

  • dos 程序的运行

  • 用debug 1.exe 逐步调试 win64 打不开不兼容

assume cs:codesg

codesg segment

start: mov ax, 2
	   add ax, ax
	   add ax, ax
	
	   mov ax, 4c00H
	   int 21H 

codesg ends

end start

  • 可以看到 debug将程序加载到内存后,cx寄存器中存放的是程序的长度,机器码一共多少个字节

1.3 exe 文件的程序加载过程

  • SA+10H:0 就是程序的入口 就是程序区

1.4 Loop 指令

  • 指令的格式是loop 标号,CPU执行loop指令时要进行两步操作

    1. (cx)= (cx)-1
    2. 判断cx中的值,不为零则跳转至标号处执行程序,如果为零则向下执行
  • cx中的值影响这loop指令的执行结果

  • 通常 我们用loop指令来实现循环功能,cx中存放循环的次数

  • 	mov cx, 10
    f:    add ax, ax
    	loop for
    
  • 执行到loop for时 先要将cx -1 若cx不为0 则跳转到for 继续执行add ax, ax,所有我们可以通过cx 来控制add ax,ax中的次数

  • assume cs:code
    code segment
    
    start:     mov ax, 2
               mov cx, 7
          s:   add ax, ax
               loop s
    
               mov ax, 4c00H
               int 21H 
    
    code ends
    end start
    
  • 实现2^8 debug loop.exe 16进制的100 等于256 cx为循环的次数

  • 执行到loop指令时 cx先减一 ,如果为0 向下执行

1.5 Loop和[bx]的联合应用

  • 计算ffff:0 ---- ffff:5 单元中数据的和 结果储存在dx中

  • 分析:运算后的结果是否超出dx所能存储的范围

    • 能否将数据直接累积到dx中?
    • 是不可以的,因为内存中的数据是8位的,不能直接加到16位的寄存器中
  • 利用一个媒介 一个16位寄存器ax 将在ax中的数据加到dx中,从而使运算的结果不会越界

  • 计算内存中1000:0 连续8个内存字节的和

  • assume cs:code
    
    code segment
    	mov ax, 1000
    	mov ds, ax
    	mov bx, 0
    	
    	mov dx, 0
    	
    	mov cx, 8
    	
    s:	mov al,	[bx]
    	mov ah, 0
    	add dx, ax
    	inc bx
    	loop s
    	
    	mov ax, 4c00H
    	int 21H
    code ends
    end	
    

1.6 一段安全的空间

  • 在8086模式中随便向一段内存空间写入内容是很危险的,因为我们不知到这段地址存放的是什么系统数据或者代码

  • unsafe 写入数据时会报错,触碰到系统内存的数据

  • assume cs:code 
    
    code segment
    	mov ax, 0
    	mov ds, ax
    	
    	mov ds:[26H], ax
    	
    	mov ax, 4c00H
    	int 21H
    code ends
    end
    
  • 一般PC机中,DOS方式下。dos和合法程序都不会使用0:200H~0:2ff这256个字节空间,所以我们使用是安全的

  • 这段内存中都是0,代表什么都没有

1.7 编程题

  • 将内存中1000:0 1000:9的数据拷贝2000:02000:9的内存中

  • assume cs:code
    
    code segment
    	mov ax, 1000H
    	mov ds,ax
    	
    	mov ax, 2000H
    	mov es, ax
    	
    	mov bx, 0
    	mov cx, 10
    	
    f:	mov dl,[bx]
    	mov es:[bx], dl
    	inc bx
    	loop f
    	
    	mov ax, 4c00H
    	int 21H
    	
    code ends
    
    end
    
  • 在代码段中使用数据,程序第一行需要使用dw(define word)来定义,数据之间用逗号隔开,第一5个字型数据的话,它们所占的内存大小是10个字节

  • end的作用

    • end除了通知编译器程序在哪里结束,还可以通知编译器程序的入口在哪里

1.8 在代码中使用栈,数据

  • 编程题 程序运行时,定义数据存放在cs:0~~cs:9,共5个字型单元,依次将这5个字单元入栈,在出栈到这5个内存单元中,实现数据的逆序存放 将数据代码,栈,数据放在不同的段

  • assume cs:code,ds:data,ss:stack
    
    data segment
    	dw 1110H,2220H,3330H,4440H,5550H
    data ends
    
    stack segment
    	dw 0,0,0,0,0
    stack ends
    
    code segment
    
    start: mov ax, stack
    	   mov ss, ax
    	   mov sp, 10
    	   
    	   mov ax, data
    	   mov ds, ax
    	   mov bx, 0
    	   mov cx, 5
    	f: push [bx]
    	   add bx, 2
    	   loop f
    	   
    	   mov bx, 0
    	   mov cx, 5
    	s: pop [bx]
    	   add bx, 2
    	   loop s
    	   
    	   mov ax, 4c00H
    	   int 21H
    	  
    code ends
    
    end start
    
posted @ 2020-12-08 22:52  immortal_mode  阅读(150)  评论(0)    收藏  举报