我想用汇编语言编写一段代码,它会将字符串中的所有大写字符更改为小写。但是,我想避免尽可能多的条件跳转。我尝试了以下代码:
Invalid combination of opcodes and operands
但是NASM在两条CMOV线路上都给出了compile 'com.android.support:design:23.1.1'
compile 'com.squareup.picasso:picasso:2.5.2'
compile 'com.squareup.retrofit:retrofit:1.9.0'
compile 'com.squareup.okhttp:okhttp:2.4.0'
错误......我不明白,这些线路有什么问题?
答案 0 :(得分:3)
来自英特尔手册中的描述o CMOVcc — Conditional Move
:
这些指令可以将16位,32位或64位值从存储器移动到通用寄存器或从一个寄存器 通用注册到另一个。
所以你可以这样做cmovb eax, [edx]
或cmovb edx, eax
,但不是cmovb [edx], eax
。
一般来说,我无法理解你的代码。似乎edx
包含字符串的地址。但是你从那个地址(mov eax, [edx]
)读取一个DWORD,即从字符串中读取4个字符,然后尝试将这4个字符用作add [eax], byte 'a' - 'A'
中的地址。
答案 1 :(得分:1)
除非您使用的是16位或更长的UniCode字符串,CMOV对于您的情况来说不是最理想的,因为目标必须是r16 / r32 / r64。因此,选择BYTE
内存操作数作为目标是不可能的,并且会导致Invalid combination of opcodes and operands
错误。唯一的可能性是选择16或32或64位寄存器作为目标,然后将另一个“MOV”操作的最低字节复制到存储器目的地。
0F 47 /r CMOVA r16, r/m16 RM Valid Valid Move if above (CF=0 and ZF=0).
0F 47 /r CMOVA r32, r/m32 RM Valid Valid Move if above (CF=0 and ZF=0).
REX.W + 0F 47 /r CMOVA r64, r/m64 RM Valid N.E. Move if above (CF=0 and ZF=0).
但我建议你使用ASCII表中的小写和小写字母仅在第5位(= 0x20)不同的情况下将字符串转换为小写的简单方法。
global tolower_cmov
tolower_cmov:
enter 0, 0
mov edx, [ebp + 8]
.back:
test byte ptr [edx], 0xff
jz .end
or byte ptr [edx], 0x20
inc edx
jmp .back
inc edx
jmp .back
.end:
leave
ret
P.S。:此代码仅依赖于处理字符(a-z,A-Z)。否则,您必须在OR
操作码之前进行范围检查。
答案 2 :(得分:0)
在Michael的帮助下,我找到了一个适合我需求的解决方案:
global tolower_cmov
tolower_cmov:
enter 0, 0
mov edx, [ebp + 8]
.back:
test [edx], byte 0xff
jz .end
xor eax, eax
xor ecx, ecx
mov eax, [edx]
mov ecx, [edx]
add ecx, dword 'a' - 'A'
cmp [edx], byte 'A'
cmovb ecx, eax
cmp [edx], byte 'Z'
cmova ecx, eax
mov [edx], ecx
inc edx
jmp .back
.end:
leave
ret