一、subs指令概述

在汇编语言中,subs指令用于将操作数2从操作数1中减去,结果保存在操作数1中,并且更新标志位。它的基本语法如下:

subs   操作数1, 操作数2

其中操作数可以是寄存器、内存数据或立即数。这条指令可以用于有符号数和无符号数的减法。

二、subs指令用法详解

subs指令的重要用途是比较两个值。如果比较的结果是小于、等于或大于,标志寄存器将根据条件代码设置相应的标志位。这些条件代码由操作数1和操作数2的差值和相等性产生。

1. 比较两个值

比较两个值是subs指令最常见的用法。这是通过将第一个值与第二个值相减来实现的,如下所示:

mov   eax, 10
mov   ebx, 20
subs  eax, ebx

执行完这段代码后,eax的值将变为-10,并且标志寄存器将相应地更新。

2. 比较指针

在汇编语言中,经常需要判断两个指针是否相等。这也可以用subs指令来实现。代码如下:

mov   esi, offset array1  ; array1和array2是两个数组的指针
mov   edi, offset array2
cmp   esi, edi
je    equal              ; 如果两个指针相等,跳转到equal

注意,这里使用了cmp指令,它也可以用于比较,但不会修改操作数。

3. 判断数值大小

除了判断两个值是否相等,subs指令还可以用于比较两个数的大小。例如,我们可以将两个数相减,如果结果小于零,第一个数就小于第二个数;如果结果等于零,两个数相等;如果结果大于零,第一个数大于第二个数。

mov   eax, 10
cmp   eax, 20
jng   less_than
jz    equal
jmp   greater_than

less_than:
    ; 第一个数小于第二个数
    ...
equal:
    ; 两个数相等
    ...
greater_than:
    ; 第一个数大于第二个数
    ...

三、subs指令示例

1. 比较两个值

section .data
  a db 10
  b db 20
section .text
  global _start
_start:
  mov   al, [a]
  mov   bl, [b]
  subs  al, bl
  jge   greater
  ; 如果a小于b,则跳转到less
  less:
    mov   edx, a
    mov   ecx, len_a
    mov   ebx, 1
    mov   eax, 4
    int   0x80
    jmp   exit
  ; 如果a大于等于b,则跳转到greater
  greater:
    mov   edx, b
    mov   ecx, len_b
    mov   ebx, 1
    mov   eax, 4
    int   0x80
    jmp   exit
exit:
  mov   eax, 1
  xor   ebx, ebx
  int   0x80
section .data
  msg_a db 'a'
  len_a equ $-msg_a
  msg_b db 'b'
  len_b equ $-msg_b

这段代码比较了变量a和变量b的值,如果a小于b,则输出字符a,否则输出字符b。

2. 比较指针

section .data
  array1 dd 1, 2, 3
  array2 dd 1, 2, 3
section .text
  global _start
_start:
  mov   esi, offset array1
  mov   edi, offset array2
  cmp   esi, edi
  je    equal
  ; 如果两个指针不相等,则跳转到not_equal
not_equal:
  mov   edx, not_equal_msg
  mov   ecx, not_equal_len
  mov   ebx, 1
  mov   eax, 4
  int   0x80
  jmp   exit
  ; 如果两个指针相等,则跳转到equal
equal:
  mov   edx, equal_msg
  mov   ecx, equal_len
  mov   ebx, 1
  mov   eax, 4
  int   0x80
  jmp   exit
exit:
  mov   eax, 1
  xor   ebx, ebx
  int   0x80
section .data
  equal_msg db 'equal'
  equal_len equ $-equal_msg
  not_equal_msg db 'not equal'
  not_equal_len equ $-not_equal_msg

这段代码比较了两个数组的指针,如果它们相等,则输出equal,否则输出not equal。

3. 判断数值大小

section .data
  a dd 5
  b dd 10
section .text
  global _start
_start:
  mov   eax, [a]
  mov   ebx, [b]
  subs  eax, ebx
  jz    equal
  jng   less_than
  ; 如果a大于b,则跳转到greater
greater:
  mov   edx, greater_msg
  mov   ecx, greater_len
  mov   ebx, 1
  mov   eax, 4
  int   0x80
  jmp   exit
  ; 如果a小于b,则跳转到less_than
less_than:
  mov   edx, less_than_msg
  mov   ecx, less_than_len
  mov   ebx, 1
  mov   eax, 4
  int   0x80
  jmp   exit
  ; 如果a等于b,则跳转到equal
equal:
  mov   edx, equal_msg
  mov   ecx, equal_len
  mov   ebx, 1
  mov   eax, 4
  int   0x80
  jmp   exit
exit:
  mov   eax, 1
  xor   ebx, ebx
  int   0x80
section .data
  greater_msg db 'a is greater than b'
  greater_len equ $-greater_msg
  less_than_msg db 'a is less than b'
  less_than_len equ $-less_than_msg
  equal_msg db 'a equals b'
  equal_len equ $-equal_msg

这段代码比较了变量a和变量b的值,如果a大于b,则输出a is greater than b;如果a小于b,则输出a is less than b;如果a等于b,则输出a equals b。