汇编记录程序问题:最长姓名长度计算错误及numpeople值异常
汇编程序错误分析与修复
问题1:numpeople值为4而非预期的6
原因
代码定义PERSON_RECORD_SIZE为72字节,对应32字节姓名区+5个8字节字段(共40字节),但实际每条记录的姓名.ascii字符串长度不足32字节,且未填充剩余空间,导致单条记录实际长度小于72字节。总记录长度endpeople - people除以72后,得到错误的结果4,而非正确的6。
修复方法
在每个姓名字符串后填充空白字节,确保姓名区占满32字节:
people: .ascii "Gilbert Keith\0" .space 32 - (.-people) # 填充至32字节长度 .quad 200, 10, 2, 74, 20 .ascii "Jonathan Barlett\0" .space 32 - (.-people) .quad 280, 12, 2, 72, 44 .ascii "Gilbert Keith Chesterfield\0" .space 32 - (.-people) .quad 150, 8, 1, 68, 30 .ascii "Tommy Aquinas\0" .space 32 - (.-people) .quad 250, 14, 3, 75, 24 .ascii "Isaac Newn\0" .space 32 - (.-people) .quad 250, 10, 4, 70, 11 .ascii "Gregory Mend\0" .space 32 - (.-people) .quad 180, 11, 5, 69, 65 endpeople:
.space N指令会填充N个空白字节,.-people计算当前位置与people起始地址的偏移,用32减去该值即可补全姓名区至32字节,确保每条记录总长度为72字节。此时(endpeople - people)/PERSON_RECORD_SIZE会正确计算为6。
问题2:程序仅返回第一个姓名的长度13
原因
由于每条记录实际长度未达到72字节,执行addq $PERSON_RECORD_SIZE, %rbx后,rbx会跳过后续有效数据,指向错误位置。读取该位置字节时直接遇到\0,导致后续记录的姓名长度被计算为0,无法更新最长长度寄存器%rdi。
修复方法
修复记录长度对齐问题后,rbx的偏移会正确指向每条记录的起始地址,程序就能正常遍历所有6条记录并统计最长姓名长度。原代码中的寻址逻辑NAME_OFFSET(%rbx, %rdx, 1)等价于%rbx + %rdx + NAME_OFFSET,逻辑本身无误,只需确保记录长度符合定义即可。
完整修复后的代码
.section .data .globl people, numpeople numpeople: .quad (endpeople - people)/PERSON_RECORD_SIZE people: .ascii "Gilbert Keith\0" .space 32 - (.-people) .quad 200, 10, 2, 74, 20 .ascii "Jonathan Barlett\0" .space 32 - (.-people) .quad 280, 12, 2, 72, 44 .ascii "Gilbert Keith Chesterfield\0" .space 32 - (.-people) .quad 150, 8, 1, 68, 30 .ascii "Tommy Aquinas\0" .space 32 - (.-people) .quad 250, 14, 3, 75, 24 .ascii "Isaac Newn\0" .space 32 - (.-people) .quad 250, 10, 4, 70, 11 .ascii "Gregory Mend\0" .space 32 - (.-people) .quad 180, 11, 5, 69, 65 endpeople: .globl NAME_OFFSET, WEIGHT_OFFSET, SHOE_OFFSET .globl HAIR_OFFSET, HEIGHT_OFFSET, AGE_OFFSET .equ NAME_OFFSET, 0 .equ WEIGHT_OFFSET, 32 .equ SHOE_OFFSET, 40 .equ HAIR_OFFSET, 48 .equ HEIGHT_OFFSET, 56 .equ AGE_OFFSET, 64 .globl PERSON_RECORD_SIZE .equ PERSON_RECORD_SIZE, 72 .globl _start .section .text _start: leaq people, %rbx movq numpeople, %rcx movq $0, %rdi movq $0, %rdx cmpq $0, %rcx je finish mainloop: movb NAME_OFFSET(%rbx, %rdx, 1), %al cmpb $0, %al je nextstring incq %rdx jmp mainloop nextstring: cmpq %rdi, %rdx cmovgq %rdx, %rdi addq $PERSON_RECORD_SIZE, %rbx movq $0, %rdx loopq mainloop finish: movq $60, %rax syscall
内容的提问来源于stack exchange,提问作者Encephalonum
相关产品推荐
相关产品推荐

