String 将字符串转换为大写
我试图在汇编中迭代一个字符串,将小写字母改为大写,并在字符串为0时停止,但似乎出现了一些错误(我似乎缺少一个概念)。我搞不清楚问题是什么或发生了什么 以下是我到目前为止的情况:String 将字符串转换为大写,string,assembly,x86-64,att,String,Assembly,X86 64,Att,我试图在汇编中迭代一个字符串,将小写字母改为大写,并在字符串为0时停止,但似乎出现了一些错误(我似乎缺少一个概念)。我搞不清楚问题是什么或发生了什么 以下是我到目前为止的情况: Upper: movq (%rbx), %rcx movq $0, %rdi call check call fin add %rdi, %rax ret fin: c
Upper:
movq (%rbx), %rcx
movq $0, %rdi
call check
call fin
add %rdi, %rax
ret
fin:
cmpb $0x0, %r9b
jne check
ret
check:
movb (%rcx, %rdi), %r9b
cmp $'Z', %r9b
jg toUpper
jmp next
toUpper:
sub %r9b, 0x20
jmp next
next:
incq %rdi
jmp fin
看起来,您的代码有点复杂,很难理解您要实现的算法 处理此类问题时,通常先用C或伪代码写下基本算法:
- 对于每个字符
c
- 如果
为空字节:完成c
- 如果
低于c
:忽略'a'
- 如果
高于c
:忽略'z'
- 其他:将
和'A'
的差异添加到'A'
c
- 如果
upper:
; Read next character
mov (%rdi), %al
; Test for zero byte
test %al, %al
je done
; Test for <'a' and >'z'
cmp $'a', %al
jl next
cmp $'z', %al
jg next
; We have a lower case character, so convert to upper case
sub $0x20, %al ; Difference between 'A' and 'a'
mov %al, (%rdi)
next:
; Increment pointer
inc %rdi
jmp upper
done:
ret
输出
Upper case: ABC 123 <=>? 987 XYZ!
大写:ABC 123?987 XYZ!
您能演示一下如何调用Upper
?它似乎没有遵循常见的调用约定。添加0xe0是编写-0x20
的一种不同寻常的方式。通常情况下,您将sub$0x20,%al
或仅使用和$~0x20,%al
屏蔽小写位。这两者都更直观。另外,通过将load/test/jnz放在底部,可以避免在循环中使用无条件的jmp
。(跳转到循环入口,或剥离第一次迭代的部分)。谢谢你指出这一点,我已经修复了添加。我只是计算了差异,并没有注意到这个数字是负数:DRegarding循环结构:我同意你的观点,但在这种情况下,尽量靠近伪代码是经过深思熟虑的。在实践中,做……而方法显然是这里的方法(或者只是用C编写程序和使用编译器……),是的,尽管我考虑了{},但是循环是ASM中循环的正常/惯用方式。但有足够的条件逻辑,添加循环条目分支可能会使代码不明显的人更难理解。顺便说一句,有一些更多的信息,包括如何使用sub/cmp/ja而不是2x cmp/jcc进行范围检查。