x86汇编条件语句的实现
Implementation of conditional statement in x86 assembly
我想知道如何将这行代码实现到 x86 masm 程序集中:
if (x >= 1 && x <= 100) {
printsomething1();
} else if (x >= 101 && x <= 200) {
printsomething2();
} else {
printsomething3();
}
如果你有一个像样的 C 编译器,你可以把它编译成汇编语言。对于 gcc
使用 -S 标志:
gcc test.c -S
这将创建文件 test.s,其中包含可以在需要时进行汇编和链接的汇编语言输出。
比如为了让你的代码编译成功,我稍微改写成这样:
#include <stdio.h>
#include <stdlib.h>
void printsomething (int y)
{
printf ("something %d", y);
}
void func (int x)
{
if (x >= 1 && x <= 100)
printsomething(1);
else
if (x >= 101 && x <= 200)
printsomething(2);
else
printsomething(3);
}
int main (int argc, char **argv)
{
int x = 0;
if (argc > 1)
x = atoi (argv [1]);
return 0;
}
它编译成这个汇编器:
.file "s.c"
.text
.section .rodata
.LC0:
.string "something %d"
.text
.globl printsomething
.type printsomething, @function
printsomething:
.LFB5:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq , %rsp
movl %edi, -4(%rbp)
movl -4(%rbp), %eax
movl %eax, %esi
movl $.LC0, %edi
movl [=12=], %eax
call printf
nop
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE5:
.size printsomething, .-printsomething
.globl func
.type func, @function
func:
.LFB6:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq , %rsp
movl %edi, -4(%rbp)
cmpl [=12=], -4(%rbp)
jle .L3
cmpl 0, -4(%rbp)
jg .L3
movl , %edi
call printsomething
jmp .L4
.L3:
cmpl 0, -4(%rbp)
jle .L5
cmpl 0, -4(%rbp)
jg .L5
movl , %edi
call printsomething
jmp .L4
.L5:
movl , %edi
call printsomething
.L4:
nop
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE6:
.size func, .-func
.globl main
.type main, @function
main:
.LFB7:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq , %rsp
movl %edi, -20(%rbp)
movq %rsi, -32(%rbp)
movl [=12=], -4(%rbp)
cmpl , -20(%rbp)
jle .L7
movq -32(%rbp), %rax
addq , %rax
movq (%rax), %rax
movq %rax, %rdi
call atoi
movl %eax, -4(%rbp)
.L7:
movl [=12=], %eax
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE7:
.size main, .-main
.ident "GCC: (GNU) 7.3.1 20180712 (Red Hat 7.3.1-6)"
.section .note.GNU-stack,"",@progbits
检查它的 func:
部分,您将看到它如何设置与 1、100、101 等的比较
我会把它分成连续的范围,(假设 x 是无符号的)像:
- x 为 0,执行 printsomething3()
- x 是 1 到 100,什么也不做 printsomething1()
- x 是 101 到 200,什么也不做 printsomething2()
- x 为 201 或更高,什么也不做 printsomething3()
然后从最低到最高工作,例如:
;eax = x;
cmp eax,0
je .printsomething3
cmp eax,100
jbe .printsomething1
cmp eax,200
jbe .printsomething2
jmp .printsomething3
如果唯一的区别是他们打印的字符串(而不是他们用来打印它的代码)我会更进一步:
mov esi,something3 ;esi = address of string if x is 0
cmp eax,0
je .print
mov esi,something1 ;esi = address of string if x is 1 to 100
cmp eax,100
jbe .print
mov esi,something2 ;esi = address of string if x is 101 to 200
cmp eax,200
jbe .print
mov esi,something3 ;esi = address of string if x is 201 or higher
jmp .print
我想知道如何将这行代码实现到 x86 masm 程序集中:
if (x >= 1 && x <= 100) {
printsomething1();
} else if (x >= 101 && x <= 200) {
printsomething2();
} else {
printsomething3();
}
如果你有一个像样的 C 编译器,你可以把它编译成汇编语言。对于 gcc
使用 -S 标志:
gcc test.c -S
这将创建文件 test.s,其中包含可以在需要时进行汇编和链接的汇编语言输出。
比如为了让你的代码编译成功,我稍微改写成这样:
#include <stdio.h>
#include <stdlib.h>
void printsomething (int y)
{
printf ("something %d", y);
}
void func (int x)
{
if (x >= 1 && x <= 100)
printsomething(1);
else
if (x >= 101 && x <= 200)
printsomething(2);
else
printsomething(3);
}
int main (int argc, char **argv)
{
int x = 0;
if (argc > 1)
x = atoi (argv [1]);
return 0;
}
它编译成这个汇编器:
.file "s.c"
.text
.section .rodata
.LC0:
.string "something %d"
.text
.globl printsomething
.type printsomething, @function
printsomething:
.LFB5:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq , %rsp
movl %edi, -4(%rbp)
movl -4(%rbp), %eax
movl %eax, %esi
movl $.LC0, %edi
movl [=12=], %eax
call printf
nop
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE5:
.size printsomething, .-printsomething
.globl func
.type func, @function
func:
.LFB6:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq , %rsp
movl %edi, -4(%rbp)
cmpl [=12=], -4(%rbp)
jle .L3
cmpl 0, -4(%rbp)
jg .L3
movl , %edi
call printsomething
jmp .L4
.L3:
cmpl 0, -4(%rbp)
jle .L5
cmpl 0, -4(%rbp)
jg .L5
movl , %edi
call printsomething
jmp .L4
.L5:
movl , %edi
call printsomething
.L4:
nop
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE6:
.size func, .-func
.globl main
.type main, @function
main:
.LFB7:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq , %rsp
movl %edi, -20(%rbp)
movq %rsi, -32(%rbp)
movl [=12=], -4(%rbp)
cmpl , -20(%rbp)
jle .L7
movq -32(%rbp), %rax
addq , %rax
movq (%rax), %rax
movq %rax, %rdi
call atoi
movl %eax, -4(%rbp)
.L7:
movl [=12=], %eax
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE7:
.size main, .-main
.ident "GCC: (GNU) 7.3.1 20180712 (Red Hat 7.3.1-6)"
.section .note.GNU-stack,"",@progbits
检查它的 func:
部分,您将看到它如何设置与 1、100、101 等的比较
我会把它分成连续的范围,(假设 x 是无符号的)像:
- x 为 0,执行 printsomething3()
- x 是 1 到 100,什么也不做 printsomething1()
- x 是 101 到 200,什么也不做 printsomething2()
- x 为 201 或更高,什么也不做 printsomething3()
然后从最低到最高工作,例如:
;eax = x;
cmp eax,0
je .printsomething3
cmp eax,100
jbe .printsomething1
cmp eax,200
jbe .printsomething2
jmp .printsomething3
如果唯一的区别是他们打印的字符串(而不是他们用来打印它的代码)我会更进一步:
mov esi,something3 ;esi = address of string if x is 0
cmp eax,0
je .print
mov esi,something1 ;esi = address of string if x is 1 to 100
cmp eax,100
jbe .print
mov esi,something2 ;esi = address of string if x is 101 to 200
cmp eax,200
jbe .print
mov esi,something3 ;esi = address of string if x is 201 or higher
jmp .print