操作我offset在汇编语言中是由编译器处理的符号,伪指令,它的功能是取得标号的偏移地址
将start的代码复制到s0中去
assume cs:code
code segment
start: mov ax, bx ;这里占两个字节
mov si, offset start ;将start的偏移地址送入si中 0000H
mov di, offset s0 ;将s0的偏移地址送入di中
mov ax, cs:[si] ;通过物理地址将数据送入ax,在通过ax送到di中
mov cs:[di], ax
s0: nop ;nop 占一个字节
nop
mov ax, 4c00H
int 21H
code ends
end start
jmp为无条件跳转指令,只可以修改ip
jmp指令需要给出两种信息
assume cs:code
code segment
start: mov ax, 0
jmp short s
add ax, 1
s: inc ax
mov ax, 4c00H
int 21H
code ends
end start
jmp short 标号(转移到标号处执行命令)
这种jmp格式指令实现的是段内短转移,它对ip的修改范围为-128~127,也就是说,它向前可以越过128个字节,向后的话最多可以越过127个字节
assume cs:code
code segment
start: mov ax, 0
jmp short ptr s
db 256 dup(0) ;这里定义256个空字节 short是跳不过去的,编译不会通过,可以改成near ptr, far ptr
s: inc ax
mov ax, 4c00H
int 21H
code ends
end start
汇编与机器码的对照
可以看到在汇编指令中出现的idata,不论它是一个数据还是偏移地址,它都会在对应的机器指令中出现,因为它是cpu执行的机器指令,他必须要处理的数据或地址,下图是上面程序对应的机器代码
CPU是如何进行转移的尼?
通过以上可以CPU 不需要目的地址也可以实现对地址的修改
ip指向03H 将指令读取到指令缓存区,ip自增2变成05H,执行执行后 ,EB是jmp的机器码 ,向后在跳3个字节,ip等于08H,这个时候执行inc ax将ax自增1
jmp short 标号的功能是(ip)= (ip)+8位偏移 8位位移是由程序在编译的时候算出的
jmp near ptr 标号说明,段内近转移 16位位移
16位位移的范围是-32768~32767
之前的jmp,其机器码中并没有转移的目的地址,而是相对于当前ip的转移偏移
jmp far ptr 标号 实现的段间转移,又称段转移
far ptr 指明了指令中标号的段地址和偏移地址改变了CS:IP
assume cs:code
code segment
start: mov ax, 0
jmp far ptr s
db 256 dup(0)
s: inc ax
mov ax, 4c00H
int 21H
code ends
end start
jmp far ptr可以看出机器码是包含要跳转的地址,没有相对于当前ip的计算转移偏移
jmp word ptr 内存单元地址
功能:内存单元存储的一个字就是转移的目的地的偏移地址
因为word是16位的只能完成段内转移,进行16位位移
代码示例
mov ax, 1234H
mov ds:[0], ax
jmp word ptr ds:[o] ;这里跳转的为CS:1234H
jmp dword ptr 内存单元地址(段间转移)
功能:从内存单元地址存放2个字,高地址对应段地址,低地址对应偏移地址 因为dword是32位的可以完成段间转移
CS=内存单元地址+2
IP= 内存单元地址
代码示例
mov ax, 1234H
mov ds:[0], ax
mov ds:[2], 0
jmp word ptr ds:[0] ;这里跳转的为CS:IP = 0000:1234H
loop为循环指令,所有循环都是短转移,对应的机器码是转移的位移,而不是物理地址
cx为0 则向下执行
在内存2000H段中查找第一个值为0的字节,找到后将偏移地址放入dx中
assume cs:code
code segment
start: mov ax, 2000H
mov ds, ax
mov bx, 0
s: mov cl, [bx]
mov ch, 0
jcxz ok
inc bx ;自增1 去找下一个内存单元的数据
loop s
ok: mov dx, bx
mov ax, 4c00H
int 21H
code ends
end start
原文:https://www.cnblogs.com/immortal-mode/p/14106188.html