由于我对汇编很新,所以如果用户在汇编中输入大写字母或反之亦然,我有一些关于如何从小写转换为大写的问题。这是我到目前为止所做的:
section .data
Enter db "Enter: "
Enter_Len equ $-Enter
Output db "Output: "
Output_Len equ $-Output
Thanks db "Thanks!"
Thanks_Len equ $-Thanks
Loop_Iter dd 0 ; Loop counter
section .bss
In_Buffer resb 2
In_Buffer_Len equ $-In_Buffer
section .text
global _start
_start:
; Print Enter message
mov eax, 4 ; sys_write
mov ebx, 1
mov ecx, Enter
mov edx, Enter_Len
int 80h
; Read input
mov eax, 3 ; sys_read
mov ebx, 0
mov ecx, In_Buffer
mov edx, In_Buffer_Len
int 80h
所以基本上,如果我是正确的,我的edx包含输入的字符串。现在出现了从低级到高级,从大写到小写的困境。因为我对此非常陌生,所以根本不知道该怎么做。任何帮助将不胜感激:))
答案 0 :(得分:5)
如果您只支持ASCII,则可以使用OR 0x20
or eax, 0x20
同样,您可以通过清除该位将字母转换为大写:
and eax, 0xBF ; or use ~0x20
正如nneonneo所提到的,可以使用XOR
指令交换字符大小写:
xor eax, 0x20
仅当eax
介于'a'和'z'或'A'和'Z'之间时才有效,所以你必须比较并确保你在范围内:
cmp eax, 'a'
jl .not-lower
cmp eax, 'z'
jg .not-lower
or eax, 0x20
.not-lower:
我使用了nasm语法。您可能还需要确保jl
和jg
也正确...
如果你需要转换任何国际字符,那么除非你可以调用接受Unicode字符的libc tolower()或toupper()函数,否则这样做会复杂得多。
作为一个公平的问题:它为什么会起作用? (kuhaku问道)
ASCII字符(也是ISO-8859-1)在0x41和0x5A之间定义了基本的大写字符,在0x61和0x7A之间定义了小写字符。
要强制4进6和5进7,强制设置第5位(0x20)。
要转到大写,你做相反的事情,你删除第5位使它变为零。
答案 1 :(得分:3)
好的,但是你的字符串不在edx
中,而是在[ecx]
(或[In_Buffer]
)中(并且它只是一个有用的字符)。获得一个角色......
mov al, [ecx]
在HLL中,您执行“如果有某些条件,请执行此代码”。您可能想知道CPU是如何知道是否执行代码。我们真正做的事情(HLL为你做这个)是“如果没有条件,跳过这个代码”(到标签)。试验一下,你会弄明白的。
干净利落地退出代码所需的任何路径。你没有表现出来,但我认为你这样做了。
我刚刚在sys_read
here上发布了一些信息。
这是一个完全不同的程序(添加两个数字 - “十六进制”数字),但关于sys_read
的部分可能会让您感兴趣...
答案 2 :(得分:0)
可爱的技巧:如果他们只输入 字母,你可以用0x20对他们的输入字母进行异或交换。
然后,如果他们可以输入多个字母,你只需要检查每个字母,看它是否是字母顺序,然后再进行异或。例如,您可以通过测试来查看它是否位于“a”到“z”或“A”到“Z”的范围内。
或者,您可以通过256个元素的表格映射每个字母,该表格按照您希望的方式映射字符(例如,这通常是toupper
等函数的实现方式。)
答案 3 :(得分:0)
这是我一起攻击的NASM程序,它翻转字符串的情况,你基本上需要循环遍历字符串并检查每个字符的ascii中的边界,然后加上或减去0x20
来改变大小写(这是ascii中上下之间的距离。您可以使用Linux ascii
命令查看ascii值表。
档案:flipcase.asm
section .text
global _start ; Entry point for linker (ld)
; Linker entry point
_start:
mov rcx,len ; Place length of message into rcx
mov rbp,msg ; Place address of our msg into rbp
dec rbp ; Adjust count to offset
; Go through the buffer and convert lowercase to uppercase characters:
upperScan:
cmp byte [rbp+rcx],0x41 ; Test input char against uppercase 'A'
jb lowerScan ; Not uppercase Ascii < 0x41 ('A') - jump below
cmp byte [rbp+rcx],0x5A ; Test input char against uppercase 'Z'
ja lowerScan ; Not uppercase Ascii > 0x5A ('Z') - jump above
; At this point, we have a uppercase character
add byte [rbp+rcx],0x20 ; Add 0x20 to get the lowercase Ascii value
jmp Next ; Done, jump to next
lowerScan:
cmp byte [rbp+rcx],0x61 ; Test input char against lowercase
jb Next ; Not lowercase Ascii < 0x61 ('a') - jump below
cmp byte [rbp+rcx],0x7A ; Test input char against lowercase 'z'
ja Next ; Not lowercase Ascii > 0x7A ('z') - jump below
; At this point, we have a lowercase char
sub byte [rbp+rcx],0x20 ; Subtract 0x20 to get the uppercase Ascii value
; Fall through to next
Next:
dec rcx ; Decrement counter
jnz upperScan ; If characters remain, loop back
; Write the buffer full of processed text to stdout:
Write:
mov rbx,1 ; File descriptor 1 (stdout)
mov rax,4 ; System call number (sys_write)
mov rcx,msg ; Message to write
mov rdx,len ; Length of message to write
int 0x80 ; Call kernel interrupt
mov rax,1 ; System call number (sys_exit)
int 0x80 ; Call kernel
section .data
msg db 'hELLO, wwwoRLD!',0xa ; Our dear string
len equ $ - msg ; Length of our dear string
然后你可以编译并运行它:
$> nasm -felf64 flipcase.asm && ld -melf_x86_64 -o flipcase flipcase.o && ./flipcase
答案 4 :(得分:0)
杰夫·丹特曼(Jeff Duntemann)写了一本名为汇编语言的汇编语言逐步编程的书......在第275-277页中很好地介绍了这个主题。
他使用代码sub byte [ebp+ecx], 20h
显示
然后您可以将小写更改为大写,请注意缓冲区使用1024个字节,这是一个更快更好的方法,然后上一个示例位于第268-269页,其中缓冲区只有8位时间。