首页 文章

汇编程序内存分配

提问于
浏览
0

我试图解决这个问题几天 . 我不知道如何分配内存来将字符串复制到另一个位置 . 这是代码:

caesarAsm proc string: DWORD, key: DWORD, stringLength : DWORD

        ; inside this procedure I have a code that ciphers string value using caesar cipher 


        mov eax, string
        ret         
caesarAsm endp

然后在我使用该功能的CPP文件中:

caesar1(word, 13, strlen(word))

它改变了通过引用传递的单词的值 . 我希望它能做什么,直到我做:

word = caesar1(word, 13, strlen(word))

我一直试图解决这个问题在互联网上搜索,但我没有发现任何有用的东西 . 我想这个解决方案很简单,但我找不到它 . 我试图用ESI和EDI寄存器做某事 . 我想我必须分配新的内存然后将字符串复制到这个分配的位置 . 怎么做?

1 回答

  • 1

    根据注释中的讨论,复制字符串的基本方法是在.bss中声明一个标签,并保留保存字符串副本所需的字节数 . 这是使用intel语法,因为我没有MASM可用 . 例如,您可以在.data中声明原始字符串 . 例如 . :

    section .data
        str_str1 db 'string one to copy', 0
    
    section .bss
        str_str2 resb 19
    

    对于副本,将 str_str1 的地址加载到 esi 中,并将 str_str2 的地址加载到 edi 中 . 在 cx 中加载要复制的字符数,然后调用 rep movsbcx 中指定的字节数从 esi 移动到 edi . 例如 . :

    section .text
                    global _start
    
            _start:
                    xor     ecx, ecx            ; clear ecx
                    cld                         ; clear direction flag (read L->R)
                    lea     esi, [str_str1]     ; load str1 in esi
                    lea     edi, [str_str2]     ; load str2 in edi
                    mov     cx, 19              ; move 19 into cx for repeat
            rep     movsb                       ; move 19 bytes from str1 -> str2
    
            exit:
                    xor     edi, edi            ; set zero exit code
                    mov     eax, 1              ; set int 0x80 number to 60 (0x3c hex)
                    int 0x80                    ; call kernel
    

    这会将 str_str 复制到 str_str2 . 然后你可以添加代码来打印它们等.Nasm提供了一种简单的宏语言来帮助重复执行任务,如读取调用和写入调用(特别是对于缩进,间距,打印等) . nasm语法中的完整示例是:

    ; Following macros simply print indents, newlines and strings to stdout
    %macro  indent  1
            mov     eax, 4
            mov     ebx, 1
            mov     ecx, tab
            mov     edx, %1
            int 0x80
    %endmacro
    
    %macro  newlns  1
            mov     eax, 4
            mov     ebx, 1
            mov     ecx, onln
            mov     edx, %1
            int 0x80
    %endmacro
    
    ; strn (string const) macro is overloaded to take 1 or 2 args
    %macro  strn    1
            mov     eax, 4
            mov     ebx, 1
            mov     ecx, %1
            mov     edx, 1
            int 0x80
    %endmacro
    
    %macro  strn    2
            mov     eax, 4
            mov     ebx, 1
            mov     ecx, %1
            mov     edx, %2
            int 0x80
    %endmacro
    
    section .data
    
        nwln db 0xa
        dnln db 0xa,0xa
        onln times 8 db 0xa     ; 8 newlines
        tab times 8 db 0x20     ; 8 spaces
        msg_str1 db 0xa, '  string_1: '
        msg_str2 db 0xa, '  string_2: '
    
        str_str1 db 'string one to copy', 0
    
    section .bss
    
        str_str2 resb 19
    
    section .text
                    global _start
    
            _start:
                    xor     ecx, ecx            ; clear ecx
                    cld                         ; clear direction flag (read L->R)
                    lea     esi, [str_str1]     ; load str1 in esi
                    lea     edi, [str_str2]     ; load str2 in edi
                    mov     cx, 19              ; move 19 into cx for repeat
            rep     movsb                       ; move 19 bytes from str1 -> str2
    
                    ; macros to print results & add newlines
                    strn    msg_str1, 13        ; print str1 msg
                    strn    str_str1, 19        ; print str1
                    strn    msg_str2, 13        ; print str2 msg
                    strn    str_str2, 19        ; print str2
                    newlns  2                   ; print 2 newlines
    
            exit:
                    xor     edi, edi            ; set zero exit code
                    mov     eax, 1              ; set int 0x80
                    int 0x80                    ; call kernel
    

    Nasm compile/link

    nasm -f elf -o obj/str_cpy_32.o str_cpy_32.asm
    ld -m elf_i386 -o bin/str_cpy_32 obj/str_cpy_32.o
    

    Output

    $ ./bin/str_cpy_32
    
      string_1: string one to copy
      string_2: string one to copy
    

    查看MASM语法差异并进行必要的更改 . 应该没有理由你不能完成同样的事情 .

    Determining String Size - 32-bit

    如上所述,为了确定未知字符串的长度,字符串本身必须以空值终止,以提供要测试的结束标记字符 . 字符串地址放在 edi 中,然后您有效地检查每个字符是否为零(数字零,而不是字符零),长度由到达空终止字符所需的迭代次数确定:

    ; szstr computes the length of a string.
    ; edi - string address
    ; edx - contains string length (returned)
    section .text
        strsz:
                xor     ecx, ecx    ; zero rcx
                not     ecx         ; set rcx = -1 (uses bitwise id: ~x = -x-1)
                xor     al,al       ; zero the al register (initialize to NUL)
                cld                 ; clear the direction flag
                repnz   scasb       ; get the string length (dec ecx through NUL)
                not     ecx         ; rev all bits of negative -> absolute value
                dec     ecx         ; -1 to skip the null-term, ecx contains length
                mov     edx, ecx    ; size returned in edx, ready to call write
                ret
    

    当然,您不必将其用作函数,您可以将代码放在汇编程序的主体中,但由于它是您经常使用的东西,因此将其用作函数会有所帮助 .

相关问题