void bubble_a(long* start, long *end) {
long *i, *last;
for (last = end; last > start; last--) {
for (i = start; i < last; i++) {
if (*(i+1) < *i) {
long t = *(i+1);
*(i+1) = *i;
*i = t;
}
}
}
}
gcc -S -Og bubble_a.c
linux 运行以上指令获得X86-64的汇编 仿照这个汇编弄出Y86-64的
.file "bubble_a.c"
.text
.globl bubble_a
.type bubble_a, @function
bubble_a:
.LFB0:
.cfi_startproc
jmp .L2
.L3:
addq $8, %rax
.L5:
cmpq %rsi, %rax
jnb .L7
movq 8(%rax), %rdx
movq (%rax), %rcx
cmpq %rcx, %rdx
jge .L3
movq %rcx, 8(%rax)
movq %rdx, (%rax)
jmp .L3
.L7:
subq $8, %rsi
.L2:
cmpq %rdi, %rsi
jbe .L8
movq %rdi, %rax
jmp .L5
.L8:
rep ret
.cfi_endproc
.LFE0:
.size bubble_a, .-bubble_a
.ident "GCC: (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0"
.section .note.GNU-stack,"",@progbits
/* bubble_a.ys */
.pos 0
irmovq stack, %rsp # Set up stack pointer
call main # Execute main program
halt # Terminate program
# Array of 4 elements
.align 8
array:
.quad 0x0000000000000004
.quad 0x0000000000000003
.quad 0x0000000000000002
.quad 0x0000000000000001
main:
irmovq array,%rdi
irmovq $4,%rsi
call bubble_a # sum(array, 4)
ret
# bubble_a(long * data,long count)
# array in %rdi, count in %rsi
bubble_a:
jmp L2
L3:
irmovq $8,%r8
addq %r8, %rax
L5:
rrmovq %rsi, %r8
rrmovq %rax, %r9
subq %r8, %r9
jge L7
mrmovq 8(%rax), %rdx
mrmovq (%rax), %rcx
rrmovq %rcx, %r8
rrmovq %rdx, %r9
subq %r8, %r9
jge L3
rmmovq %rcx, 8(%rax)
rmmovq %rdx, (%rax)
jmp L3
L7:
irmovq $8,%r8
subq %r8,%rsi
L2:
rrmovq %rdi, %r8
rrmovq %rsi, %r9
subq %r8, %r9
jle L8
rrmovq %rdi, %rax
jmp L5
L8:
ret
.pos 200
stack:
bubble_a.ys文件保存在一个Y86-64模拟器文件夹中
Y86-64模拟器的安装攻略请自行百度,注意只支持ubuntu-18及以下的系统。
终端键入指令:
make bubble_a.yo
模拟器会根据bubble_a.ys生成bubble_a.yo文件 以此验证是否编译成功
| /* bubble_a.ys */
0x000: | .pos 0
0x000: 30f4c800000000000000 | irmovq stack, %rsp # Set up stack pointer
0x00a: 803800000000000000 | call main # Execute main program
0x013: 00 | halt # Terminate program
|
| # Array of 4 elements
0x018: | .align 8
0x018: | array:
0x018: 0400000000000000 | .quad 0x0000000000000004
0x020: 0300000000000000 | .quad 0x0000000000000003
0x028: 0200000000000000 | .quad 0x0000000000000002
0x030: 0100000000000000 | .quad 0x0000000000000001
|
0x038: | main:
0x038: 30f71800000000000000 | irmovq array,%rdi
0x042: 30f60400000000000000 | irmovq $4,%rsi
0x04c: 805600000000000000 | call bubble_a # sum(array, 4)
0x055: 90 | ret
|
|
| # bubble_a(long * data,long count)
| # array in %rdi, count in %rsi
|
0x056: | bubble_a:
0x056: 70c600000000000000 | jmp L2
0x05f: | L3:
0x05f: 30f80800000000000000 | irmovq $8,%r8
0x069: 6080 | addq %r8, %rax
0x06b: | L5:
0x06b: 2068 | rrmovq %rsi, %r8
0x06d: 2009 | rrmovq %rax, %r9
0x06f: 6189 | subq %r8, %r9
0x071: 75ba00000000000000 | jge L7
0x07a: 50200800000000000000 | mrmovq 8(%rax), %rdx
0x084: 50100000000000000000 | mrmovq (%rax), %rcx
0x08e: 2018 | rrmovq %rcx, %r8
0x090: 2029 | rrmovq %rdx, %r9
0x092: 6189 | subq %r8, %r9
0x094: 755f00000000000000 | jge L3
0x09d: 40100800000000000000 | rmmovq %rcx, 8(%rax)
0x0a7: 40200000000000000000 | rmmovq %rdx, (%rax)
0x0b1: 705f00000000000000 | jmp L3
0x0ba: | L7:
0x0ba: 30f80800000000000000 | irmovq $8,%r8
0x0c4: 6186 | subq %r8,%rsi
0x0c6: | L2:
0x0c6: 2078 | rrmovq %rdi, %r8
0x0c8: 2069 | rrmovq %rsi, %r9
0x0ca: 6189 | subq %r8, %r9
0x0cc: 71e000000000000000 | jle L8
0x0d5: 2070 | rrmovq %rdi, %rax
0x0d7: 706b00000000000000 | jmp L5
0x0e0: | L8:
0x0e0: 90 | ret
|
0x0c8: | .pos 200
0x0c8: | stack:
最后梳理以下本题要点:
Y86比较两个数只能用subq指令,不支持直接数运算并且减法后会改变第二个寄存器的值。比较时,一般将两个值保存在新的寄存器当中。
本答案仅依据 gcc -S -Og bubble_a.c 生成的文件改成Y86-64格式。源c文件的函数并没有问题,但是最终结果符不符合预期并没有检验。