如何获取字符串的起始地址而不是整个字符串的地址

时间:2015-02-08 21:14:31

标签: assembly x86 nasm

如果我让你对这个问题感到困惑,我很抱歉,但我不知道更好地描述它

我正在尝试编写一个NASM程序来反转字符串。

我有3个函数:strlen,readstring和asm_main

readstring:从用户输入读取并将其存储在保留空间“inputstring”

    push ebp        ; setup routine
    mov ebp, esp
    ;;;;;;;;;;;;;;;;;;;;;;;;;; 
    mov eax, message
    call print_string   ; print"please enter your string message"

    mov eax, 3  ; read
    mov ebx, 1  ; from standard input
    mov ecx,inputstring;  store at memory locaton inputstring
    mov edx, 100        ; 100 byte
    int 0x80

    mov eax, inputstring

   ;;;;;;;;;;;;;;;;;;;;;
    pop ebp
    ret

稍后,我使用另一个子程序“strlen”来获取用户输入的长度

问题是

在我的主程序中,我有两个寄存器保存开头和最后一个字符的地址。所以ecx持有开始,ebx持有最后一个字符

让我说我输入“abcde”,

所以我将$ ecx指向字符串的开头,$ ebx指向最后一个字符(即e \ n)。我的问题是,当我交换ecx和ebx时,我是否用最后一个字符(e / n)交换整个字符串(abcde)?

或者我是否将第一个字符(a)与最后一个字符(e / n)交换?

当我尝试在GDB中打印出每个寄存器的内容时​​。

ecx:abede / n

ebx:e / n

所以我将整个字符串与最后一个字符交换,这绝对不是我想要的。那么我哪里做错了???有人可以给我一个暗示吗?

这是我的代码

%include "asm_io.inc"
segment .data
message db "Please enter your string message: ", 0xA,0
formatin db "%d", 0xA


segment .bss
   inputstring: resb 100

segment .text
    global asm_main
    extern printf
    extern scanf


**asm_main**:
    enter 0, 0
    pusha

    ;;;;;;;;;;;;;;;;;;;;;;;;
    call readstring
    mov ecx, eax    ; now ecx contains the begin address
    call strlen     ; when return, eax will hold the length

    push eax        ; we need eax in the loop

    ; use edi as temporary pointer
    ; use ebx to point to the last char

    mov ebx, 0    ;initialize ebx to 0
    add ebx, ecx  ; ebx = ecx now, ebx points to the beginning
    add ebx, eax  ; ebx = ecx + eax, now it points to then end
    sub ebx, 1    ; ebx = ecx +eax -1, now it points to the 
                  ; last char

while:
    cmp ebx, ecx   ; cmp end , begining
    jle exitWhile

    mov edi, [ebx]    ; temp = *end
    mov eax,[ecx]   ; *end = *begining
    mov [ebx], eax
    mov [ecx], edi    ; *beginning = temp

    inc ecx
    dec ebx

    jmp while

exitWhile:

    pop eax
    popa
    mov eax, 0
    leave           ; missing this line will cause segmentation 
                    ; fault, why?
    ret

**readstring**:
    push ebp        ; setup routine
    mov ebp, esp
    ;;;;;;;;;;;;;;;;;;;;;;;;;; 
    mov eax, message
    call print_string

    mov eax, 3  ; read
    mov ebx, 1  ; from standard input
    mov ecx,inputstring;  store at memory locaton inputstring
    mov edx, 100        ; 100 byte
    int 0x80

    mov eax, inputstring

   ;;;;;;;;;;;;;;;;;;;;;
    pop ebp
    ret


**strlen**:
    push ebp
    mov ebp, esp

    push esi
    ;;;;;;;;;;;;;;;;;;;;;
    mov esi, ecx    ; now esi contains the address of string
    mov edx, 0     ;  edx will be int i
loop:
    mov al, [esi]   ; al 
    cmp al, 0xA     ; check if al holds an ASCII new line
    je  exitLoop

    inc esi
    inc edx

    cmp esi, inputstring+100; see if esi is pointing past the end
                    ; of the 100 reserved byte

    jl loop


exitLoop:
    ;;;;;;;;;;;;;;;;;;;;
    mov eax, edx
    pop esi
    pop ebp
    ret

1 个答案:

答案 0 :(得分:0)

由于您正在为作业使用32位寄存器,因此您一次交换四个字符。你交换" abcd"与" e \ n ??" (其中??是字符串后面的两个字节)。对ASCII字符使用8位寄存器:

while:
  cmp ebx, ecx   ; cmp end , begining
  jle exitWhile

  mov al,[ebx]
  xchg al,[ecx]
  mov [ebx],al

  inc ecx
  dec ebx

  jmp while

exitWhile: