Converting a C program to inline Assembly? - c

I am trying to convert the following C program to inline assembly:
#include <stdio.h>
#include <string.h>
int main()
{
int counter = 0;
int input = 0;
char name[20];
printf("Please input an integer value 1 - 99: ");
scanf("%d", &input);
printf("You entered: %d\n", input);
if (input <= 0)
{
printf("Error, invalid input \n");
}
if (input > 0)
{
printf("Please input name \n");
scanf("%s", name);
for (int i = 1; i <=input; i++)
{
printf("Your name is %s\n", name);
printf("%d\n", i);
}
}
return 0;
}
Here is my attempt at the inline:
.LC0:
.string "please input an interger value 1-99"
.LC1:
.string "%d"
.LC2:
.string "you entered %d"
.LC3:
.string "Error invalid input"
.LC4:
.string "please input name"
.LC5:
.string "%s"
.LC6:
.string "Your name is %s"
main:
push rbp
mov rbp, rsp
sub rsp, 32
mov DWORD PTR [rbp-8], 0
mov DWORD PTR [rbp-12], 0
mov edi, OFFSET FLAT:.LC0
mov eax, 0
call printf
lea rax, [rbp-12]
mov rsi, rax
mov edi, OFFSET FLAT:.LC1
mov eax, 0
call scanf
mov eax, DWORD PTR [rbp-12]
mov esi, eax
mov edi, OFFSET FLAT:.LC2
mov eax, 0
call printf
mov eax, DWORD PTR [rbp-12]
test eax, eax
jg .L2
mov edi, OFFSET FLAT:.LC3
mov eax, 0
call printf
.L2:
mov eax, DWORD PTR [rbp-12]
test eax, eax
jle .L3
mov edi, OFFSET FLAT:.LC4
mov eax, 0
call printf
lea rax, [rbp-32]
mov rsi, rax
mov edi, OFFSET FLAT:.LC5
mov eax, 0
call scanf
mov DWORD PTR [rbp-4], 1
jmp .L4
.L5:
lea rax, [rbp-32]
mov rsi, rax
mov edi, OFFSET FLAT:.LC6
mov eax, 0
call printf
mov eax, DWORD PTR [rbp-4]
mov esi, eax
mov edi, OFFSET FLAT:.LC1
mov eax, 0
call printf
add DWORD PTR [rbp-4], 1
.L4:
mov eax, DWORD PTR [rbp-12]
cmp DWORD PTR [rbp-4], eax
jle .L5
.L3:
mov eax, 0
leave
ret
So I guess my question is, am I on the right track? I find this stuff extremely confusing. It doesn't help that all my instructor sais is that "I am on the right track" so any help would be much appreciated! (Whenever I run this I get an error on the first line complaining about the ".")

Thank you guys! Figured out that the inline was unnecessary and that we were supposed to be doing regular assembly! Really appreciate the help!

Related

How to convert assembly with multiple if statements to c code?

cmp eax, 1
je .L3
cmp eax, 4
je .L4
jmp .L9
.L3:
mov DWORD PTR [ebp-16], 1
jmp .L5
.L4:
mov DWORD PTR [ebp-16], 2
jmp .L5
I need some help figuring out how exactly to convert this to C code. I've tried doing a nested if statement but it converts to
cmp eax, 1
je .L3
cmp eax, 4
je .L3
The code I tried was this
if (var1 != 1)
{
if(var1!=4)
{
var2=1;
}
}
Entire Assembly code for context
push ebp
mov ebp, esp
sub esp, 16
mov DWORD PTR [ebp-4], 4
mov DWORD PTR [ebp-16], 0
mov DWORD PTR [ebp-8], 0
mov eax, DWORD PTR [ebp-4]
cmp eax, 1
je .L3
cmp eax, 4
je .L4
jmp .L9
.L3:
mov DWORD PTR [ebp-16], 1
jmp .L5
.L4:
mov DWORD PTR [ebp-16], 2
jmp .L5
.L9:
mov DWORD PTR [ebp-16], 3
.L5:
mov DWORD PTR [ebp-12], 0
jmp .L6
.L7:
mov eax, DWORD PTR [ebp-12]
add DWORD PTR [ebp-8], eax
add DWORD PTR [ebp-12], 1
.L6:
mov eax, DWORD PTR [ebp-12]
cmp eax, DWORD PTR [ebp-16]
jl .L7
mov eax, 0
leave
ret
That code should be assimilated to:
if (var1 == 1)
goto l3;
else if (var1 == 4) // we use the same value in eax so the same variable is being checked
goto l4;
else goto l9;
l3: var2 = 1; goto l5;
l4: var2 = 2; goto l5;
l9: var2 = 3;
l5: ...
I should use a switch statement, as all the tests depend on the value of the var1 variable (indeed, the value of var1 is evaluated and stored into eax, and this is the value compared all the time) giving:
switch (var1) {
case 1: var2 = 1; break;
case 4: var2 = 2; break;
default: var2 = 3; break;
}

how to draw the stack after analysing the assembly code

pleasse i need someone to assit me with my assighnment.
q1. Examine the code below and Draw the stack frame after analysing the assembly code when function1, function2 and function3 are called by the main program for a 32-bit system. Figure 2 shows a sample stack frame of a function.
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
int function1(int x, int y, int z)
{
int result_func1;
result_func1 = x + y + z;
return result_func1;
}
int function2(int x, int y, char* input_string)
{
int result_func2;
char buffer[20];
strcpy(buffer, input_string);
printf("your input string %s is copied in the buffer \n", input_string);
result_func2= x - y;
return result_func2;
}
void function3(int result1, int result2)
{
printf("The result of function 1 is %d\n", result1);
printf("The result of function 1 is %d\n", result1);
}
void function4(void)
{
printf("The function never gets called is \n");
exit(-1);
}
int main(int argc, char* argv[])
{
int result1;
int result2;
result1 = function1(5, 10, 15);
result2 = function2(20, 8, argv[1]);
function3(result1, result1);
}
assembly code of the after the analysis:
0x00005555555552c0 <+0>: endbr64
0x00005555555552c4 <+4>: push %rbp
0x00005555555552c5 <+5>: mov %rsp,%rbp
0x00005555555552c8 <+8>: sub $0x20,%rsp
0x00005555555552cc <+12>: mov %edi,-0x14(%rbp)
0x00005555555552cf <+15>: mov %rsi,-0x20(%rbp)
0x00005555555552d3 <+19>: mov $0xf,%edx
0x00005555555552d8 <+24>: mov $0xa,%esi
0x00005555555552dd <+29>: mov $0x5,%edi
0x00005555555552e2 <+34>: callq 0x5555555551c9 <function1>
0x00005555555552e7 <+39>: mov %eax,-0x8(%rbp)
0x00005555555552ea <+42>: mov -0x20(%rbp),%rax
0x00005555555552ee <+46>: add $0x8,%rax
0x00005555555552f2 <+50>: mov (%rax),%rax
0x00005555555552f5 <+53>: mov %rax,%rdx
0x00005555555552f8 <+56>: mov $0x8,%esi
0x00005555555552fd <+61>: mov $0x14,%edi
0x0000555555555302 <+66>: callq 0x5555555551ef <function2>
0x0000555555555307 <+71>: mov %eax,-0x4(%rbp)
0x000055555555530a <+74>: mov -0x8(%rbp),%edx
0x000055555555530d <+77>: mov -0x8(%rbp),%eax
0x0000555555555310 <+80>: mov %edx,%esi
0x0000555555555312 <+82>: mov %eax,%edi
0x0000555555555314 <+84>: callq 0x555555555261 <function3>
0x0000555555555319 <+89>: mov $0x0,%eax
0x000055555555531e <+94>: leaveq
0x000055555555531f <+95>: retq
modidied(actual 32bit assembly code)
function1:
push ebp
mov ebp, esp
mov eax, DWORD PTR [ebp+12]
add eax, DWORD PTR [ebp+8]
add eax, DWORD PTR [ebp+16]
pop ebp
ret
.LC0:
.string "your input string %s is copied in the buffer \n"
function2:
push ebp
mov ebp, esp
push ebx
lea eax, [ebp-28]
sub esp, 44
mov ebx, DWORD PTR [ebp+16]
push ebx
push eax
call strcpy
pop eax
pop edx
push ebx
push OFFSET FLAT:.LC0
call printf
mov eax, DWORD PTR [ebp+8]
mov ebx, DWORD PTR [ebp-4]
sub eax, DWORD PTR [ebp+12]
leave
ret
.LC1:
.string "The result of function 1 is %d\n"
function3:
push ebp
mov ebp, esp
push ebx
sub esp, 12
mov ebx, DWORD PTR [ebp+8]
push ebx
push OFFSET FLAT:.LC1
call printf
mov DWORD PTR [ebp+12], ebx
add esp, 16
mov ebx, DWORD PTR [ebp-4]
mov DWORD PTR [ebp+8], OFFSET FLAT:.LC1
leave
jmp printf
.LC2:
.string "The function never gets called is "
function4:
push ebp
mov ebp, esp
sub esp, 20
push OFFSET FLAT:.LC2
call puts
mov DWORD PTR [esp], -1
call exit
main:
lea ecx, [esp+4]
and esp, -16
push DWORD PTR [ecx-4]
push ebp
mov ebp, esp
push ecx
sub esp, 8
mov eax, DWORD PTR [ecx+4]
push DWORD PTR [eax+4]
push 8
push 20
call function2
pop edx
pop ecx
push 30
push 30
call function3
mov ecx, DWORD PTR [ebp-4]
xor eax, eax
leave
lea esp, [ecx-4]
ret
please i need someone who can assist me with who to start

Is there an O(1) method to choose between n branches in C, like with an array of function pointers or array of goto labels?

I'm working on a calculator, and at the part where operations are actually executed, I have a big long switch block that looks something like this (the cases go up linearly starting at 1):
switch(operator) {
case 1:
a = a + b;
break;
case 2:
a = a - b;
break;
...
case 20:
a = sin(a);
break;
I have quite a few operators and functions at this point and testing each case one at a time doesn't seem like it would be the fastest option.
Is there a way to use a table (such as an array of goto labels, or an array of function pointers) so that the "operator" variable would cause the program to jump to the appropriate operation without the program having to test for each of the cases? If so, how would I go about doing this, given the above code?
It can not be faster then switch and I will show you why. Here is my version of your function with switch
void switch_fun(int operator) {
switch(operator) {
case 0:
a = a + b;
break;
case 1:
a = a - b;
break;
case 2:
a = a * b;
break;
}
}
Which translate to this assembler (with comments for non-assembly people)
switch_fun:
push rbp
mov rbp, rsp
mov DWORD PTR [rbp-4], edi ## copy 'operator'
cmp DWORD PTR [rbp-4], 2 ## compare 'operator' with 2
je .L2 ## if 'operator' is equal to 2 jump to .L2 (few lines below)
cmp DWORD PTR [rbp-4], 0 ## same comparition for 0
je .L4
cmp DWORD PTR [rbp-4], 1 ## and for 1
je .L5
jmp .L6 ## if nothing match jump at the end of the function
.L4:
mov edx, DWORD PTR a[rip]
mov eax, DWORD PTR b[rip]
add eax, edx ## addition, like in case 0:
mov DWORD PTR a[rip], eax
jmp .L3 ## jump at the end
.L5:
mov eax, DWORD PTR a[rip]
mov edx, DWORD PTR b[rip]
sub eax, edx ## subtraction
mov DWORD PTR a[rip], eax
jmp .L3
.L2:
mov edx, DWORD PTR a[rip]
mov eax, DWORD PTR b[rip]
imul eax, edx ## multiplication
mov DWORD PTR a[rip], eax
nop
.L3:
.L6:
nop
pop rbp
ret
It's pretty simple construction and probably impossible to optimize even more, but let's try. Here I have version of this function but with array of addresses to goto labels.
void array_fun(int operator) {
void* labels[] = {&&addition, &&subtraction, &&mul};
goto *labels[operator];
addition:
a = a + b;
goto outer;
subtraction:
a = a - b;
goto outer;
mul:
a = a * b;
outer:
return;
}
Ignoring fact that this code is really unsafe because if operator will be greater then 2 this will crash program but whatever, let's see how this look in assembly.
array_fun:
push rbp
mov rbp, rsp
mov DWORD PTR [rbp-36], edi
mov QWORD PTR [rbp-32], OFFSET FLAT:.L8
mov QWORD PTR [rbp-24], OFFSET FLAT:.L9
mov QWORD PTR [rbp-16], OFFSET FLAT:.L10 ## here you eliminated some comparitions
## but add some new 'moves' and calculations, everything below is practically the same like in first function, it's definitely not faster, probably slower then switch
mov eax, DWORD PTR [rbp-36]
cdqe
mov rax, QWORD PTR [rbp-32+rax*8]
nop
jmp rax
.L8:
mov edx, DWORD PTR a[rip]
mov eax, DWORD PTR b[rip]
add eax, edx
mov DWORD PTR a[rip], eax
jmp .L12
.L9:
mov eax, DWORD PTR a[rip]
mov edx, DWORD PTR b[rip]
sub eax, edx
mov DWORD PTR a[rip], eax
jmp .L12
.L10:
mov edx, DWORD PTR a[rip]
mov eax, DWORD PTR b[rip]
imul eax, edx
mov DWORD PTR a[rip], eax
.L12:
nop
pop rbp
ret
TL;DR don't try to optimize switch on integers because it's impossible to do
EDIT: With array of pointers to functions it would be even worse because you will get overhead because of calling a function

assembly output + questions about stacks

I was studying one of my courses when I ran into a specific exercise that I cannot seem to resolve... It is pretty basic because I am VERY new to assembly. So lets begin.
I have a C function
unsigned int func(int *ptr, unsigned int j) {
unsigned int res = j;
int i = ptr[j+1];
for(; i<8; ++i) {
res >>= 1;
}
return res;
}
I translated it with gcc to assembly
.file "func.c"
.intel_syntax noprefix
.text
.globl func
.type func, #function
func:
.LFB0:
.cfi_startproc
push rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
mov rbp, rsp
.cfi_def_cfa_register 6
mov QWORD PTR [rbp-24], rdi
mov DWORD PTR [rbp-28], esi
mov eax, DWORD PTR [rbp-28]
mov DWORD PTR [rbp-8], eax
mov eax, DWORD PTR [rbp-28]
add eax, 1
mov eax, eax
lea rdx, [0+rax*4]
mov rax, QWORD PTR [rbp-24]
add rax, rdx
mov eax, DWORD PTR [rax]
mov DWORD PTR [rbp-4], eax
jmp .L2
.L3:
shr DWORD PTR [rbp-8]
add DWORD PTR [rbp-4], 1
.L2:
cmp DWORD PTR [rbp-4], 7
jle .L3
mov eax, DWORD PTR [rbp-8]
pop rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size func, .-func
.ident "GCC: (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4"
.section .note.GNU-stack,"",#progbits
The question is as follow. what is the command that place j (variable in the c function) on top of the stack?
I sincerely cannot find out please enlighten me XD.
The variable j is the second parameter for func; it is stored in the register esi in the x86-64 System V ABI calling convention. This instruction mov DWORD PTR [rbp-28], esi put j into the stack.
You can see it very clearly by writing a simple function that calls "func" and compiling it with -O0 (or with -O2 and marking it as noinline, or only providing a prototype so there's nothing for the compiler to inline).
unsigned int func(int *ptr, unsigned int j) {
unsigned int res = j;
int i = ptr[j+1];
for(; i<8; ++i) {
res >>= 1;
}
return res;
}
int main()
{
int a = 1;
int array[10];
func (array, a);
return 0;
}
Using the Godbolt compiler explorer, we can easily get gcc -O0 -fverbose-asm assembly output.
Please focus on the following instructions:
# in main:
...
mov DWORD PTR [rbp-4], 1
mov edx, DWORD PTR [rbp-4]
...
mov esi, edx
...
func(int*, unsigned int):
...
mov DWORD PTR [rbp-28], esi # j, j
...
j, j is a comment added by gcc -fverbose-asm tell you that the source and destination operands are both the C variable j in that instruction.
The full assembly instructions:
func(int*, unsigned int):
push rbp
mov rbp, rsp
mov QWORD PTR [rbp-24], rdi
mov DWORD PTR [rbp-28], esi
mov eax, DWORD PTR [rbp-28]
mov DWORD PTR [rbp-4], eax
mov eax, DWORD PTR [rbp-28]
add eax, 1
mov eax, eax
lea rdx, [0+rax*4]
mov rax, QWORD PTR [rbp-24]
add rax, rdx
mov eax, DWORD PTR [rax]
mov DWORD PTR [rbp-8], eax
jmp .L2
.L3:
shr DWORD PTR [rbp-4]
add DWORD PTR [rbp-8], 1
.L2:
cmp DWORD PTR [rbp-8], 7
jle .L3
mov eax, DWORD PTR [rbp-4]
pop rbp
ret
main:
push rbp
mov rbp, rsp
sub rsp, 48
mov DWORD PTR [rbp-4], 1
mov edx, DWORD PTR [rbp-4]
lea rax, [rbp-48]
mov esi, edx
mov rdi, rax
call func(int*, unsigned int)
mov eax, 0
leave
ret
Taking into account these instructions
mov eax, DWORD PTR [rbp-28]
add eax, 1
it seems that j is stored at address rbp-28 While ptr is stored at address rbp-24.
These are instructions where the values are stored in the stack
mov QWORD PTR [rbp-24], rdi
mov DWORD PTR [rbp-28], esi
It seems the arguments are passed to the function using registers rdi and esi.
Compilers can optimize their calls of functions and use registers instead of the stack to pass arguments of small sizes to functions. Within the functions they can use the stack to temporary store the arguments passed through registers.
Just a suggestion for further explorations on your own. Use gcc -O0 -g2 f.c -Wa,-adhln. It will turn off optimizations and generate assembly code intermixed with the source. It might give you better ideas about what it does.
As an alternative you can use the objdump -Sd f.o on the output '.o' or executable. Just make sure that you add debugging info and turn off optimizations at compilation.

x86 Struct scanf

I am trying to convert C to x86. I am using a struct...
struct person_record_struct
{
char last_name[128];
char first_name[128];
char year_of_birth[10];
int month_of_birth; // January => 1
int day_of_birth; // 1st Day of a Month => 1
char drivers_license_no[128];
};
typedef struct person_record_struct person_record;
I am having trouble getting my scanf to work. Here is the C..
result = scanf("%s\n%s\n%s\n%d\n%d\n%s\n", &records[counter].last_name[0],
&records[counter].first_name[0], &records[counter].year_of_birth[0],
&records[counter].month_of_birth, &records[counter].day_of_birth,
&records[counter].drivers_license_no[0]);
And my x86..
;counter # [ebp-4]
;records # [ebp-16]
; format_string_main_2 db '%s\n%s\n%s\n%d\n%d\n%s\n', 0
; read in info
; push drivers_license_no
mov ebx, [ebp-16] ;
mov eax, [ebp-4]
mov ecx, struct_size
mul ecx
add eax, ebx
lea eax, [eax+276]
push eax
; push day_of_birth
mov ebx, [ebp-16]
mov eax, [ebp-4]
mov ecx, struct_size
mul ecx
add eax, ebx
lea eax, [eax+272]
push eax
; push month_of_birth
mov ebx, [ebp-16]
mov eax, [ebp-4]
mov ecx, struct_size
mul ecx
add eax, ebx
lea eax, [eax+268]
push ax
; push year_of_birth
mov ebx, [ebp-16]
mov eax, [ebp-4]
mov ecx, struct_size
mul ecx
add eax, ebx
lea eax, [eax+256]
push eax
; push first_name
mov ebx, [ebp-16]
mov eax, [ebp-4]
mov ecx, struct_size
mul ecx
add eax, ebx
lea eax, [eax+128]
push eax
; push last_name
mov ebx, [ebp-16]
mov eax, [ebp-4]
mov ecx, struct_size
mul ecx
add eax, ebx
lea eax, [eax+0]
push eax
push format_string_main_2
call scanf
add esp, 28
mov [ebp-12], eax
I'm using a check to see if result is 6 and if it's not my program that prints an error and exits. It keeps having an error and I'm not sure what I am doing wrong. Any help would be much appreciated. Thank you.
This is my calloc call which appears to be correct...
; // allocate the buffer of all the records
; records = (person_record *)calloc(number_of_records, sizeof(person_record));
push struct_size
mov eax, [ebp-8]
push eax
call calloc
add esp, 8
mov [ebp-16], eax
Under month_of_birth you have push ax instead of push eax. This would push only the lower 16 bits of the address on the stack, virtually guaranteeing a crash in scanf. Fix that and it should be OK.
There are many weird/wrong things going on in your code. It will be easier to show a cleaner way. You have not mentioned the Assembler you are using, there are a few for x86 and each has its own syntax. Here is how you can do it using NASM:
extern printf, scanf, calloc, exit, free, puts
global main
struc person_record
.last_name resb 128
.first_name resb 128
.year_of_birth resb 10
.month_of_birth resd 1
.day_of_birth resd 1
.drivers_license_no resb 128
.size equ $ - person_record
endstruc
MAX_RECORDS equ 2
section .data
Space db 32, 0
input_format db "%s%s%s%d%d%s", 0
output_format db "%s %s %s %d %d %s", 0
section .text
main:
push person_record.size
push MAX_RECORDS
call calloc
add esp, 4 * 2
mov esi, eax
mov ebx, eax
mov edi, MAX_RECORDS - 1
.FillRecord:
lea eax, [ebx + person_record.drivers_license_no]
push eax
lea ecx, [ebx + person_record.day_of_birth]
push ecx
lea edx, [ebx + person_record.month_of_birth]
push edx
lea eax, [ebx + person_record.year_of_birth]
push eax
lea ecx, [ebx + person_record.first_name]
push ecx
lea edx, [ebx + person_record.last_name]
push edx
push input_format
call scanf
add esp, 4 * 7
push Space
call puts
add esp, 4 * 1
add ebx, person_record.size
dec edi
jns .FillRecord
mov ebx, esi
mov edi, MAX_RECORDS - 1
.ShowRecord:
lea eax, [ebx + person_record.drivers_license_no]
push eax
mov ecx, [ebx + person_record.day_of_birth]
push ecx
mov edx, [ebx + person_record.month_of_birth]
push edx
lea eax, [ebx + person_record.year_of_birth]
push eax
lea ecx, [ebx + person_record.first_name]
push ecx
lea edx, [ebx + person_record.last_name]
push edx
push output_format
call printf
add esp, 4 * 7
push Space
call puts
add esp, 4 * 1
add ebx, person_record.size
dec edi
jns .ShowRecord
push esi
call free
add esp, 4 * 1
push 0
call exit
And the input and output of 2 records:

Resources