//2019年天津大学智算学部汇编语言程序设计-李罡
//2020年08月09日 15时05分15秒
The direction depends on DF, if DF = 1 they decrease
cld # clear the DF (= 0), increase
std # set the DF (= 0), decrease
.section .data
value1:
.ascii “This is a test string.\n”
.section .bss
.lcomm output, 23
.section .text
.globl main
main:
leal value1, %esi
leal output, %edi
movl $23, %ecx
cld
loop1: # 第一种
movsb
loop loop1
rep movsb # 第二种
Using rep prefix to transfer string by bytes.
ECX is used to count the loop.
movl $1, %eax
movl $0, %ebx
int $0x80
#rep prefix to ransfer by blocks
# Eg. to transfer 8 bytes, when using movsb, ecx should be 8.
# If using movsw, ecx is set to 4
# Pay attention to out-of-boundary
# Eg. String length is 23 bytes. If ecx = 6, using movsl
# will transfer 24 bytes.
(gdb) x/s &output
#ox601058 : “This is a test string.\nO”
.section .data
value1:
.ascii “This is a test string.\n”
value2:
.ascii “Oops”
.section .bss
.lcomm output, 23
.section .text
.globl main
main:
leal value1, %esi
leal output, %edi
movl $6, %ecx
cld
rep movsl
movl $1, %eax
movl $0, %ebx
int $0x80
/*
wannian07@wannian07-PC:~$ gcc hello.s -o hello
wannian07@wannian07-PC:~$ ./hello
wannian07@wannian07-PC:~$
#2020年08月09日 15时31分10秒
.section .data
string1:
.ascii “This is a test of the conversion program!\n”
length:
.int 43 # length = .-output 计算长度
divisor: # 除法 %4
.int 4
.section .bss
.lcomm buffer, 43
.section .text
.globl main
main:
leal string1, %esi
leal buffer, %edi
movl length, %ecx # ecx = 43
shrl $2, %ecx # % 4 43 % 4 = 10 3
cld
rep movsl # 做10次 rep
movl length, %ecx # ecx = 43
andl $3, %ecx # 逐位与3 (0011) 高位清零, 个位保留
rep movsb # 做3次 rep 一共用了10 + 3 次
movl $1, %eax
movl $0, %ebx
int
0
x
80
/
∗
w
a
n
n
i
a
n
07
@
w
a
n
n
i
a
n
07
−
P
C
:
0x80 /* wannian07@wannian07-PC:~
0x80/∗ wannian07@wannian07−PC: gcc hello.s -o hello
wannian07@wannian07-PC:~$ ./hello
wannian07@wannian07-PC:~$
#lods?
load (%esi) to AL/AX/EAX/RAX and increase / decrease esi(on DF = 0/1)
rep lodsl (in fact, rep is useless with lodsl, for there is only one eax)
#stos?
Store AL/AX/EAX/RAX to (%edi) and increase / decrease esi(on DF = 0/1)
rep stosl (fill the memory with one value)
.section .data
space:
.ascii “” # 用空格填入一片内存
.section .bss
.lcomm buffer, 256
.section .text
.globl main
main:
leal space, %esi
leal buffer, %edi
movl $256, %ecx
cld
lodsb
rep stosb
movl $1, %eax
movl $0, %ebx
int $0x80
wannian07@wannian07-PC:~$ gcc hello.s -o hello
wannian07@wannian07-PC:~$ ./hello
wannian07@wannian07-PC:~$
#fill buffer with space
#Esi, edi, eax, ecx are used
.section .data
string1:
.ascii “This is a TEST, of the conversion program!\n”
length:
.int 43
.section .text
.globl main
main:
leal string1, %esi
movl %esi, %edi
movl length, %ecx
cld
loop1: #所有小写字母, 改写成大写字母
lodsb #取第一个字符 T, 与a-z 比较.
cmpb $‘a’, %al
jl skip # 比较小 跳转skip
cmpb $‘z’, %al
jg skip # 比较大,跳转skip
subb $0x20, %al # 所有符合条件的, 减去al-20 变成大写字母
skip:
stosb
loop loop1
print:
movl $4, %eax
movl $1, %ebx
movl $string1, %ecx
movl length, %edx
int $0x80
end:
movl $1, %eax
movl $0, %ebx
int $0x80
//2020年08月09日 16时19分50秒
.section .data
value1:
.ascii “Test”
value2:
.ascii “Test”
.section .text
.globl main
main:
movl $1, %eax #比较两个字符串, 相等返回0, 不等返回 1
leal value1, %esi
leal value2, %edi
cld
cmpsl
je equal
movl $1, %ebx
int $0x80
equal:
movl $0, %ebx
int $0x80
/*
wannian07@wannian07-PC:~$ gcc hello.s -o hello
wannian07@wannian07-PC:~$ ./hello
wannian07@wannian07-PC:~$ echo $?
0
cmps?
compare (%esi) with (%edi)
in the example, cmpsl compares 4 bytes.
meaning (%edi) - (%esi)
.section .data
value3:
.ascii “This is a test of the CMPS instructions”
value4:
.ascii “This is a test of the CMPS Instructions”
.section .text
.globl main
main:
movl $1, %eax
leal value3, %esi
leal value4, %edi
movl $39, %ecx
cld
repe cmpsb # 两字符比较, edi - esi
je equal #相等ZF= 1,循环 , 不相等,退出 ;cx = 0 退出
movl %ecx, %ebx # ecx 剩下的沒有做的數,
int $0x80
equal:
movl $0, %ebx
int $0x80
rep with cmps
but rep only checks ecx
other than check ecx, there are reps checking zf.
REPE Loop if equal Check if ZF == 0
REPNE Loop if not equal Check if ZF != 0
REPZ Loop if zero Same as REPE
REPNZ Loop if not zero Same as REPNE
.section .data
string1:
.ascii “test”
length1:
.int 4
string2:
.ascii “test1”
length2:
.int 5
.section .text
.globl main
main:
lea string1, %esi
lea string2, %edi
movl length1, %ecx
movl length2, %eax
cmpl %eax, %ecx
ja longer
xchg %ecx, %eax
longer:
cld
repe cmpsb
je equal
je greater
less:
movl $1, %eax
movl $225, %ebx
int $0x80
greater:
movl $1, %eax
movl $1, %ebx
int $0x80
equal:
movl length1, %ecx
movl length2, %eax
cmpl %ecx, %eax
jg greater
jl less
movl $1, %eax
movl $0, %ebx
int $0x80
wannian07@wannian07-PC:~$ gcc hello.s -o hello
wannian07@wannian07-PC:~$ ./hello
wannian07@wannian07-PC:~$ echo $?
225
test > boom
test < van
test > Test 大于 返回 1
test < test1 小于 返回225
相等 长度一样返回 0
//http://c.biancheng.net/view/3682.html
SCASB、SCASW 和 SCASD 指令分别将 AL/AX/EAX 中的值与 EDI 寻址的一个字节 / 字 / 双字进行比较。这些指令可用于在字符串或数组中寻找一个数值。结合 REPE(或 REPZ)前缀,当 ECX > 0 且 AL/AX/EAX 的值等于内存中每个连续的值时,不断扫描字符串或数组。
REPNE 前缀也能实现扫描,直到 AL/AX/EAX 与某个内存数值相等或者 ECX = 0。
repne scanb (stop loop scan if %al equals (%edi))
扫描是否有匹配字符下面的例子扫描字符串 alpha,在其中寻找字符 F。如果发现该字符,则 EDI 指向匹配字符后面的一个位置。如果未发现匹配字符,则 JNZ 执行退出:
.data
alpha BYTE "ABCDEFGH",0
.code
mov edi,OFFSET alpha ;ED工指向字符串
mov al, 'F' ;检索字符F
mov ecx,LENGTHOF alpha ;设置检索计数器
cld ;方向为正向
repne seasb ;不相等则重复
jnz quit ;若未发现字符则退出
dec edi ;发现字符:EDI 减 1
循环之后添加了 JNZ 以测试由于 ECX=0 且没有找到 AL 中的字符而结束循环的可能性。
*/
.section .data
string1:
.ascii “This is a test - a long text string to scan.”
length:
.int 44
string2:
.ascii “-”
.section .text
.globl main
main:
leal string1, %edi
leal string2, %esi
movl length, %ecx
lodsb
cld
#REPNE 先检查CX是否为0, 不为0则循环.
repne scasb #当CX0或者ZF1的时候终止循环.
jne notfound
subw length, %cx
neg %cx
movl $1, %eax
movl %ecx, %ebx
int $0x80
notfound:
movl $1, %eax
movl $0, %ebx
int $0x80
/*
wannian07@wannian07-PC:~$ gcc hello.s -o hello
wannian07@wannian07-PC:~$ ./hello
wannian07@wannian07-PC:~$ echo $?
16
# 在第16的位置找到了,所要求的
涉及到三个寄存器:ECX, AL, EDI 和标志寄存器的ZF位和DF位.
*/