本文主要是介绍《汇编语言程序设计》例子之查找最大数,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
以下是第5章中讲到的 CMOV 的指令的例子,原来的源码是这样的:
# cmovtest.s - An example of the CMOV instructions
.section .data
output:.asciz "The largest value is %d\n"
values:.int 105, 235, 61, 315, 134, 221, 53, 145, 117, 5
.section .text
.globl _start
_start:nopmovl values, %ebxmovl $1, %edi
loop:movl values(, %edi, 4), %eaxcmp %ebx, %eaxcmova %eax, %ebxinc %edicmp $10, %edijne looppushl %ebxpushl $outputcall printfaddl $8, %esppushl $0call exit
当前使用环境为 Linux cnhz-cmpl42 4.15.0-197-generic #208-Ubuntu SMP Tue Nov 1 17:23:37 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux,这个程序是没法运行的。所以修改成如下:
# cmovtest.s - An example of the CMOV instructions
.section .data
output:.asciz "The largest value is %d\n"
values:.int 105, 235, 61, 315, 134, 21, 53, 145, 1117, 50
temp:.quad 0 #用于存放最大的那个数,因为这个参数是要加载到 rsi 寄存器的,如果用直接用原来的 ebx,则在 movl %ebx, %rsi 无法编译过,即使用 movq 也不行,#所以用一个临时变量存放
.section .text
.globl main
main:nopmovl $temp, %ecx #将 temp的地址加载到 ecx 寄存器movl values, %ebxmovl $1, %edi
loop:movl values(, %edi, 4), %eaxcmp %ebx, %eaxcmova %eax, %ebxmovl %ebx, (%ecx) #将最大值存放到 ecx 寄存器中地址所指的位置inc %edicmp $10, %edijne loopmovq $output, %rdimovq temp, %rsimovq $0, %raxcall printfret
Makefile:
CC = gcc
CFLAGS = -g -no-pie
SRCS = $(shell ls -t | grep "\.s$$" | head -1)a.out: $(SRCS)$(CC) -o $@ $(SRCS) $(CFLAGS).PHONY: clean
clean:rm -rf a.out
修改点:
1,修改入口点为 main,因为我直接用的 gcc 编译,Makefile 如上所示。
2,参数传送方式不一样了,movq $output, %rdi 和 movq temp, %rsi 传递第1、2 个参数,但在传递第2个参数时,如果直接用 movq %ecx, %rsi 会出现编译错误,这是两个不一样长度的寄存器,刚学我也不知道该如何正确使用,所以添加了一个临时变量来存放最大数,然后再从这个临时变量加载到 %rsi 寄存器中以达到目的。
以下还有另外一种写法,用的都是64位寄存器的名称,即全部使用以 r_ 开头的寄存器:
#cmov_test.s -- An example of the CMOV instructions
.section .data
output:.string "The largest value is %d\n"
value: # 定义成 quad,即元素大小为 8 字节,所以下面的 value(,%rdi,8) 这里为 8.quad 15, 24, 61, 36, 134, 221, 63, 145, 117, 59.section .text
.global main
main:nopmovq value, %rbx # 将 value 的第一个元素加载到 rbx 寄存器movq $1, %rdi # 将立即数 1 加载到 rdi 寄存器
loop:movq value(, %rdi, 8), %rax # 将偏移 value (%edi * 8) 个字节位置的值加载到 rax 寄存器,即第2、3、4、5、... 个元素cmp %rbx, %rax # 比较两个寄存器里值的大小cmova %rax, %rbx # 如果rax 里的值大于 rbx 里的值,则将 rax 里的值加载到 rbxinc %rdi # 自增加 1cmp $10, %rdi # 比较 rdi 里的值和立即数10,类似检查数组下标jne loop # jump not equal -- 假如不等于则跳转到 loop 标签movq $output, %rdimovq %rbx, %rsimovq $0, %raxcall printfret
这篇关于《汇编语言程序设计》例子之查找最大数的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!