如何在 Assembly 中拆分/截断字符串变量值?
How to split / truncate a string variable value in Assembly?
我目前正在做一个项目,为了存储的缘故,我想在汇编中切断一个变量,并(可选)使它成为一个寄存器的值,例如 eax。
我需要使用 Intel 语法与 NASM 一起工作的代码。
例如,如果变量 "msg" 设置为“29ak49”,我想取其中的一部分,例如“9ak4”,并将其放入寄存器或类似的东西中。
正如评论中提到的Peter Cordes,您始终可以在现有字符串的缓冲区中添加一个空终止符(0
)以进行右截断;如果您不介意修改原始字符串数据。
下面的示例将在不修改原始字符串的情况下检索子字符串。
如果你有一个变量的地址,并且知道要截断它的位置,你可以取数据起始位置的地址,并在左截断处添加一个偏移量。要右截断,您可以从新偏移量中读取任意数量的字符。
例如 x86
:
msg db '29ak49' ; create a string (1 byte per char)
;; left truncate
mov esi, msg ; get the address of the start of the string
add esi, OFFSET_INTO_DATA ; offset into the string (1 byte per char)
;; right truncate
mov edi, NUM_CHARS ; number of characters to take
.loop:
movzx eax, byte [esi] ; get the value of the next character
;; do something with the character in eax
inc esi
dec edi
jnz .loop
;; end loop
编辑:
以下是作为 32 位 Linux 应用程序的可运行测试实现,它打印出根据 OFFSET_INTO_DATA
和 NUM_CHARS
选择的子字符串(note:算法是一样的,只是寄存器变了):
section .text
global _start
_start:
;; left truncate
mov esi, msg ; get the address of the start of the string
add esi, OFFSET_INTO_DATA ; offset into the string (1 byte per char)
;; right truncate
mov edi, NUM_CHARS ; number of characters to take
.loop:
mov ecx, esi ; get the address of the next character
call print_char_32
inc esi
dec edi
jnz .loop
jmp halt
;;; input: ecx -> character to display
print_char_32:
mov edx, 1 ; PRINT
mov ebx, 1 ;
mov eax, 4 ;
int 0x80 ;
ret
halt:
mov eax, 1 ; EXIT
int 0x80 ;
jmp halt
section .data
msg db '29ak49' ; create a string (1 byte per char)
OFFSET_INTO_DATA EQU 1
NUM_CHARS EQU 3
编译:
nasm -f elf substring.asm ; ld -m elf_i386 -s -o substring substring.o
我目前正在做一个项目,为了存储的缘故,我想在汇编中切断一个变量,并(可选)使它成为一个寄存器的值,例如 eax。
我需要使用 Intel 语法与 NASM 一起工作的代码。
例如,如果变量 "msg" 设置为“29ak49”,我想取其中的一部分,例如“9ak4”,并将其放入寄存器或类似的东西中。
正如评论中提到的Peter Cordes,您始终可以在现有字符串的缓冲区中添加一个空终止符(0
)以进行右截断;如果您不介意修改原始字符串数据。
下面的示例将在不修改原始字符串的情况下检索子字符串。
如果你有一个变量的地址,并且知道要截断它的位置,你可以取数据起始位置的地址,并在左截断处添加一个偏移量。要右截断,您可以从新偏移量中读取任意数量的字符。
例如 x86
:
msg db '29ak49' ; create a string (1 byte per char)
;; left truncate
mov esi, msg ; get the address of the start of the string
add esi, OFFSET_INTO_DATA ; offset into the string (1 byte per char)
;; right truncate
mov edi, NUM_CHARS ; number of characters to take
.loop:
movzx eax, byte [esi] ; get the value of the next character
;; do something with the character in eax
inc esi
dec edi
jnz .loop
;; end loop
编辑:
以下是作为 32 位 Linux 应用程序的可运行测试实现,它打印出根据 OFFSET_INTO_DATA
和 NUM_CHARS
选择的子字符串(note:算法是一样的,只是寄存器变了):
section .text
global _start
_start:
;; left truncate
mov esi, msg ; get the address of the start of the string
add esi, OFFSET_INTO_DATA ; offset into the string (1 byte per char)
;; right truncate
mov edi, NUM_CHARS ; number of characters to take
.loop:
mov ecx, esi ; get the address of the next character
call print_char_32
inc esi
dec edi
jnz .loop
jmp halt
;;; input: ecx -> character to display
print_char_32:
mov edx, 1 ; PRINT
mov ebx, 1 ;
mov eax, 4 ;
int 0x80 ;
ret
halt:
mov eax, 1 ; EXIT
int 0x80 ;
jmp halt
section .data
msg db '29ak49' ; create a string (1 byte per char)
OFFSET_INTO_DATA EQU 1
NUM_CHARS EQU 3
编译:
nasm -f elf substring.asm ; ld -m elf_i386 -s -o substring substring.o