《汇编语言程序设计》例子之查找最大数

        以下是第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:
   nop
   movl values, %ebx
   movl $1, %edi
loop:
   movl values(, %edi, 4), %eax
   cmp %ebx, %eax
   cmova %eax, %ebx
   inc %edi
   cmp $10, %edi
   jne loop
   pushl %ebx
   pushl $output
   call printf
   addl $8, %esp
   pushl $0
   call 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:
   nop
   movl $temp, %ecx		#将 temp的地址加载到 ecx 寄存器
   movl values, %ebx
   movl $1, %edi
loop:
   movl values(, %edi, 4), %eax
   cmp %ebx, %eax
   cmova %eax, %ebx
   movl %ebx, (%ecx)	#将最大值存放到 ecx 寄存器中地址所指的位置
   inc %edi
   cmp $10, %edi
   jne loop
   
   movq $output, %rdi
   movq temp, %rsi
   movq $0, %rax
   call printf
   
   ret

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:
	nop
	movq 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 里的值加载到 rbx
	inc %rdi						# 自增加 1
	cmp $10, %rdi					# 比较 rdi 里的值和立即数10,类似检查数组下标
	jne loop						# jump not equal -- 假如不等于则跳转到 loop 标签
	
	movq $output, %rdi
	movq %rbx, %rsi
	movq $0, %rax
	
	call printf
	ret

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值