You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在TASM中通过字符串操作实现用户输入字符串的逆序存储与显示

Reverse a String Using x86 String Operations (With pushf/popf for Flag Preservation)

Perfect, let's tackle this exactly how you want it—using string operations, preserving the flag register with pushf/popf, and avoiding alternative methods like manual array indexing. Here's a step-by-step breakdown and implementation:

Key Background

First, a quick recap to align with your knowledge:

  • std sets the Direction Flag (DF) to 1, making string instructions traverse memory from high to low addresses (ESI/EDI automatically decrement after each operation).
  • cld sets DF to 0 for forward traversal (ESI/EDI increment).
  • We use pushf before std to save the current EFLAGS register (including the original DF state), then popf afterward to restore it—critical to avoid breaking any subsequent code that relies on the original direction setting.

Implementation (NASM Syntax, Linux x86)

Let's write a complete example that takes an input string, reverses it to an uninitialized variable, and prints the result:

section .data
    input_str db "Hello, Stack Overflow!", 0  ; Example input string (C-style null-terminated)
    str_len equ $ - input_str - 1             ; Length of the string (exclude null terminator)

section .bss
    rev_str resb str_len                      ; Uninitialized variable to store reversed string

section .text
    global _start

_start:
    ; 1. Save the original flag register state (critical for restoring DF later)
    pushf

    ; 2. Set direction flag to reverse traversal
    std

    ; 3. Set up source and destination pointers
    lea esi, [input_str + str_len - 1]  ; ESI = last character of input string (e.g., "!")
    lea edi, [rev_str + str_len - 1]    ; EDI = last byte of the uninitialized rev_str
    mov ecx, str_len                    ; ECX = number of characters to copy

    ; 4. Reverse the string with a single string operation
    rep movsb                           ; Automatically copies ECX bytes:
                                        ; - Each copy: [EDI] = [ESI]
                                        ; - ESI and EDI decrement each time (thanks to std)

    ; 5. Restore the original flag register (resets DF to its initial state)
    popf

    ; 6. Print the reversed string (Linux syscall)
    mov eax, 4          ; sys_write
    mov ebx, 1          ; stdout file descriptor
    lea ecx, [rev_str]  ; pointer to reversed string
    mov edx, str_len    ; length of string to print
    int 0x80

    ; Exit the program
    mov eax, 1          ; sys_exit
    xor ebx, ebx        ; exit code 0
    int 0x80

How It Works

Let's walk through the core logic with the example input "Hello, Stack Overflow!":

  1. Flag Preservation: pushf saves the current EFLAGS to the stack—this ensures we don't leave DF set to 1 for any code that runs after this routine.
  2. Reverse Traversal Setup: std tells string instructions to work backward. We point ESI to the last character of the input (!) and EDI to the last byte of rev_str.
  3. String Copy: rep movsb repeats the move operation str_len times. Each iteration copies the byte at ESI to EDI, then decrements both registers. This effectively copies the input string from end to start into rev_str from end to start—resulting in a fully reversed string in rev_str.
  4. Flag Restoration: popf pulls the original EFLAGS back from the stack, resetting DF to whatever it was before we ran std.

Alternative: Manual Loop with lodsb/stosb

If you prefer to handle each character explicitly (instead of rep movsb), here's a modified loop version:

; Replace the rep movsb section with this:
reverse_loop:
    lodsb               ; AL = [ESI], then ESI-- (due to std)
    stosb               ; [EDI] = AL, then EDI--
    loop reverse_loop   ; Decrement ECX, loop until ECX = 0

Note that for this to work, EDI still needs to start at rev_str + str_len - 1—each stosb will place the character in the next lower address of rev_str, building the reversed string correctly.

Critical Notes

  • Always calculate the string length correctly: For C-style null-terminated strings, subtract 1 to exclude the 0 terminator.
  • The pushf/popf pair is non-negotiable if your program has other string operations later—leaving DF set to 1 will break any forward-traversing string instructions (like those using cld).

内容的提问来源于stack exchange,提问作者King0fChaos97

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 03:38:52