如何测试字符串中的字符[Assembly]

时间:2013-11-17 23:23:16

标签: assembly x86 nasm

我正在编写一个程序来搜索字符串中的元音,但是我在测试字符串中的单个字符时遇到了问题,我有基本概念,我在使用C ++和Python之前已经完成了这个,但是我不知道如何在Assembly中编写代码。

我将使用一个开关来添加和测试单个字符,我知道我需要使用一个循环来循环遍历所有字符,但我坚持实际测试单个字符。 (这不是我所说的编码,而是一个说明性的例子)

max_length     dd      40
user_input     resd    max_length
str_len        dw      $ - user_input
GetStr         user_input             ; "I am a boy"
mov            ecx, str_len

这就是我被困的地方。您如何测试user_input的个别角色?

在C ++中你会有类似if(user_input[0] = 'Y')的东西,但是如何将这种类型的指令转换为汇编(user_input [0])

我知道它在汇编时不会这样做,但希望这会清除一些事情。

str_len DW      $ - user_input
max_length      EQU  40

jump_table:   
        DD      case_0
        DD      case_1
        DD      case_2
        DD      case_3
        DD      case_4
        DD      case_5

.UDATA

user_input    resd      max_length


_main:
    push    ebp
    mov     ebp, esp

switch:    
    xor     eax,eax
    xor     ebx,ebx
    PutStr  prompt
    GetStr   user_input
    mov     ecx, [str_len]
    mov     esi, user_input

read:    
    mov     al, byte [esi+ebx]
    or      al, 20h
    cmp     al, 'a'
    je      [jump_table]
    cmp     al, 'e'
    je      [jump_table+4]
    cmp     al, 'i'
    je      [jump_table+8]
    cmp     al, 'o'
    je      [jump_table+12]
    cmp     al, 'u'
    je      [jump_table+16]
    cmp     ecx, 0
    je      [jump_table+20]
    inc     ebx
    jmp     read

这就是我现在所处的地方,因为我进一步评论说我收到了与str_len相关的错误

这一切都正常,我只需要清除缓冲区,谢谢!     str_len DD 40     max_length EQU 40

jump_table:   
        DD      case_0
        DD      case_1
        DD      case_2
        DD      case_3
        DD      case_4
        DD      case_5

.UDATA

user_input    resb      max_length

.CODE

.STARTUP

switch:    
    xor     eax,eax
    xor     ebx,ebx
    xor     esi, esi
    PutStr  prompt
    GetStr  user_input
    mov     ecx, [str_len]
    mov     esi, user_input

read:    
    mov     al, byte [esi+ebx]
    or      al, 20h
    ;PutCh   al
    cmp     al, 'a'
    je      vowel_A
    cmp     al, 'e'
    je      vowel_E
    cmp     al, 'i'
    je      vowel_I
    cmp     al, 'o'
    je      vowel_O
    cmp     al, 'u'
    je      vowel_U
    cmp     ecx, 0
    je      str_end
    inc     ebx
    dec     ecx
    jmp     read

2 个答案:

答案 0 :(得分:1)

您似乎缺少的是索引寻址的概念。

如果你不知道这一点,你真的需要回到汇编程序101课程,否则你就不会去 取得很大进展我相信你可以在网上找到一个教程。

关键思想是a)寄存器包含任意值,解释为“只是一个数字”或解释为内存地址,b)您可以组合这些值来获取/存储事物到内存。鉴于寄存器(esi)包含指向字符串基数的指针,并且寄存器ecx包含字符串的索引,指令

 mov al,[edx+ecx]

将获取8位值到AL寄存器。该指令告诉计算机在edx和ecx中添加值以形成内存地址,并获取该位置中的任何内容。相关说明:

mov  [edx+ecx],al

计算相同的地址,但将AL中的内容移动到内存中。

不幸的是,对于您来说,x86 CPU对使用索引寻址形成内存地址所允许的内容有着复杂的规则,还有关于如何指定操作数(8,16,32,64)的大小的附加规则。这不是完整教程的地方,这就是为什么我建议你在继续学习之前做更多功课。

答案 1 :(得分:0)

mov EAX, [user_input]不会将字符串加载到eax中,而是加载字符串的前4个字节。

user_input是指针。

    mov     esi, user_input
    xor     ebx, ebx
SearchForVowel:
    mov     al, byte [esi + ebx]
    test    al, al          ; does al contain a 0
    jz      .Done           ; yes we are done.

    ; check to see if al contains a vowel
    if al does not contain a vowel, jump to NoVowel
    otherwise, increment vowel_counter

.NoVowel:
    inc     ebx
    jmp     SearchForVowel

.Done:

无需存储字符串长度,因为字符串为NULL终止。