How to import a library from C to a Assembly code? - c

I'm trying to convert a C code to Assembly but I have a problem in the Assembly code. In the C code i'm importing the 'conio.h' library to use the getch() function, but in the Assembly code when I have the call of this function the output says error because the getch() function is undefined. I've already tried use the extern command in the asm code but it didnt work. Any ideias how to solve this?
C code for reference:
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
int main()
{
int cont=0;
char *string;
string = (char*)malloc(sizeof(char)*20);
do{
string[cont] = getch();
cont++;
}while (string[cont] != '\0');
printf("%s", string);
return 0;
}
Assembly code for reference:
.intel_syntax
.global main
.text
main:
push %rbp
mov %rbp, %rsp
push %rbx
sub %rsp, 40
mov DWORD PTR [%rbp-28], 0
mov %edi, 20
call malloc
mov QWORD PTR [%rbp-24], %rax
.L2:
mov %eax, DWORD PTR [%rbp-28]
cdqe
mov %rbx, %rax
add %rbx, QWORD PTR [%rbp-24]
mov %eax, 0
call getch ; Call of the getch function
mov BYTE PTR [%rbx], %al
inc DWORD PTR [%rbp-28]
mov %eax, DWORD PTR [%rbp-28]
cdqe
add %rax, QWORD PTR [%rbp-24]
movzx %eax, BYTE PTR [%rax]
test %al, %al
jne .L2
mov %rsi, QWORD PTR [%rbp-24]
mov %edi, OFFSET FLAT:.LC0
mov %eax, 0
call printf
mov %eax, 0
add %rsp, 40
pop %rbx
leave
ret
.LC0:
.string "%s"

Related

Trying to translate C program to reverse a number into x86 assembly

I'm trying to translate the following program to x86 assembly ( AT&T ).
#include <stdio.h>
int main()
{
int n = 123;
int reverse = 0;
while (n != 0)
{
reverse = reverse * 10;
reverse = reverse + n%10;
n = n/10;
}
printf("%d\n", reverse);
return 0;
}
It's supposed to print 321.
However, with the code below, I'm getting a 0 instead.
Can anybody give me a clue about what I'm doing wrong here?
( I pasted just the relevant section below. I'm sure that initialization and printing are working fine. You can see the whole thing here)
movl $123, %esi # int n
movl $0, %edi # int reverse
movl $10, %ebx # divisor
L1: # while n != 0
cmpl $0, %esi
je L2
# reverse = reverse * 10
imul $10, %edi
# reverse = reverse + n % 10
movl $0, %edx
movl %edi, %eax
idivl %ebx
addl %edx, %edi
# n = n / 10
movl %esi, %eax
movl $0, %edx
idivl %ebx
movl %eax, %esi
jmp L1
L2: # end while
movl %edi, %eax
Maybe I'm not yet perfectly understanding what the idivl command is supposed to do. I understand that it divides %edx:%eax by %ebx and stores the quotient in %eax and the remainder in %edx.
# reverse = reverse + n % 10
movl $0, %edx
movl %edi, %eax ; <--- here
%edi is not n, according to the comments above:
movl $123, %esi # int n
So, it should be using %esi, i.e. movl %esi, %eax.
sometimes it is good to see what the compiler generates
int reverse(int x)
{
int r = 0;
while (x != 0)
{
r = r * 10;
r = r + x%10;
x = x/10;
}
return r;
}
and shortest version:
reverse:
xor eax, eax
mov esi, 10
.L2:
test edi, edi
je .L5
imul ecx, eax, 10
mov eax, edi
cdq
idiv esi
mov edi, eax
lea eax, [rdx+rcx]
jmp .L2
.L5:
ret
or the fastest:
reverse:
xor eax, eax
test edi, edi
je .L4
mov esi, 1717986919
.L3:
lea ecx, [rax+rax*4]
mov eax, edi
imul esi
mov eax, edi
sar eax, 31
sar edx, 2
sub edx, eax
lea eax, [rdx+rdx*4]
add eax, eax
sub edi, eax
test edx, edx
lea eax, [rdi+rcx*2]
mov edi, edx
jne .L3
rep ret
.L4:
rep ret
as you see the compilers same good/better than the 99.99% of the coders

I cannot find where the logical errors are in these two loops. GAS/AT&T Assembly

The goal of this function is to replicate the strupr C function. It's stuck in an infinite iteration and I cannot figure out why, it doesn't seem to end. The way I'm looking at it is the argv from the command line is sent as a single array of chars, I simply try to access it and determine if it has to be changed and then printed - or simply just printed. It receives a single parameter which is that very same argv value.
void lowerToUpper (char *msg);
.globl lowerToUpper
.type lowerToUpper, #function
lowerToUpper:
mov $0,%r12
lea (%rdi), %rdx
jmp .restartLoop
.restartLoop:
add $8, %rdx
cmp $0,%r13
jne .isValid
ret
.isValid:
cmp $97, %r13
jbe .printValue
jg .changeValue
.changeValue:
#sub $32, %r13
jmp .printValue
.printValue:
mov $format2, %edi
mov %r13, %rsi
mov $0, %eax
call printf
add $1,%rdx
jmp .restartLoop
The goal of this function is to print the highest number in an array. It receives a pointer to an unsigned int (an array of numbers) and it's length.
void printHigher (unsigned int *data, int len);
printHigher:
mov $0,%r14
mov $0,%r15
jmp .Loop
ret
.Loop:
mov (%rdi), %r8
cmp %r8,%rdi
jl .calculateMax
jmp .printMax
.calculateMax:
cmp %r8, %r15
jg .assignMax
add $1,%r14
add $8,(%rdi)
jmp .Loop
.assignMax:
mov %r8, %r15
.printMax:
mov $format, %edi
mov %r15, %rsi
mov $0, %eax
call printf

Segmentation fault in assembly code + C

I am trying to debug a segmentation fault in my assembly code. Here is the GDB output
Program received signal SIGSEGV, Segmentation fault.
0x0000000000424c50 in restore_context()
(gdb) disassemble restore_context
Dump of assembler code for function restore_context:
0x0000000000424c44 <+0>: mov 0x8(%rsp),%rax
0x0000000000424c49 <+5>: mov 0x38(%rax),%rsp
0x0000000000424c4d <+9>: mov (%rax),%rdx
=>0x0000000000424c50 <+12>: mov %rdx,(%rsp)
0x0000000000424c54 <+16>: mov 0x18(%rax),%rbx
0x0000000000424c58 <+20>: mov 0x20(%rax),%rsi
0x0000000000424c5c <+24>: mov 0x28(%rax),%rdi
0x0000000000424c60 <+28>: mov 0x30(%rax),%rbp
0x0000000000424c64 <+32>: xor %rax,%rax
0x0000000000424c67 <+35>: retq
End of assembler dump.
By the little research I did , this looks like a over flow error. Can someone tell me how to debug this ? How to find this memory leak. Do we have some tool to inspect this or is their an error with my assembly code. Need help debugging this.
Here is the assembly code as well
.align 4,0x90
.global restore_context
.type restore_context,#function
restore_context:
mov 8(%rsp),%rax
mov 56(%rax), %rsp
mov 0(%rax),%rdx /* Fetch our return address */
mov %rdx, 0(%rsp) /* Save our return address */ // overflow
mov 24(%rax),%rbx
mov 32(%rax), %rsi
mov 40(%rax), %rdi
mov 48(%rax), %rbp
xor %rax,%rax
ret
This is the counterpart store_context()
.align 4,0x90
.global store_context
.type store_context,#function
store_context:
mov 8(%rsp),%rax
mov %rbx, 24(%rax)
mov %rsi, 32(%rax)
mov %rdi, 40(%rax)
mov %rbp, 48(%rax)
mov %rsp, 56(%rax)
mov 0(%rsp), %rdx
mov %rdx, 0(%rax)
xor %rax,%rax
inc %rax
ret

Explain compiled code structure and static allocation

I was looking at the difference in C between char* c = "thomas"; and char c[] = "thomas";. I saw questions about this here and while trying to understand the answers I wanted to check that I was right by looking at the assembly. And a few questions were born.
Here is what I thought :
char* c = ... : the characters are allocated somewhere on the static memory (read only from the program's perspective), alongside with the code. That's why it should be marked const. The string can be printed but not modified.
char c[] = ... : Same as 1. except that when a function is called, the characters are copied in an array on the stack, so it can be modified etc etc.
I wanted to check this so I made this C code :
#include <stdio.h>
int main(){
char c [] = "thomas blabljbflkjbsdflkjbds";
printf("%s\n", c);
}
Looking at the generated assembly :
0x400564 <main>: push rbp
0x400565 <main+1>: mov rbp,rsp
0x400568 <main+4>: sub rsp,0x30
0x40056c <main+8>: mov rax,QWORD PTR fs:0x28
0x400575 <main+17>: mov QWORD PTR [rbp-0x8],rax
0x400579 <main+21>: xor eax,eax
0x40057b <main+23>: mov DWORD PTR [rbp-0x30],0x6978616d
0x400582 <main+30>: mov DWORD PTR [rbp-0x2c],0x6220656d
0x400589 <main+37>: mov DWORD PTR [rbp-0x28],0x6c62616c
0x400590 <main+44>: mov DWORD PTR [rbp-0x24],0x6c66626a
0x400597 <main+51>: mov DWORD PTR [rbp-0x20],0x73626a6b
0x40059e <main+58>: mov DWORD PTR [rbp-0x1c],0x6b6c6664
0x4005a5 <main+65>: mov DWORD PTR [rbp-0x18],0x7364626a
0x4005ac <main+72>: mov BYTE PTR [rbp-0x14],0x0
0x4005b0 <main+76>: lea rax,[rbp-0x30]
0x4005b4 <main+80>: mov rdi,rax
0x4005b7 <main+83>: call 0x400450 <puts#plt>
0x4005bc <main+88>: mov rdx,QWORD PTR [rbp-0x8]
0x4005c0 <main+92>: xor rdx,QWORD PTR fs:0x28
0x4005c9 <main+101>: je 0x4005d0 <main+108>
So characters are copied into the stack, which is what I thought.
Questions :
The characters are stored by bytes at addresses 0x6978616d, 0x6220656d and so on. Why aren't they allocated contiguously in an array ? Simple optimization of the compiler ?
explains why char* doesn't behave like an array and why c[10] isn't the 11th character of the string. However it doesn't explain why
char* c = "thomas blabljbflkjbsdflkjbds";
printf("%s\n", c);
works. (Note the [] -> *). I guess that printf reads characters by characters until it reaches a 0, so knowing just c (i.e &c[0]) how does it access c[10] ? (because of the non contiguous and the fact that this time chars are not copied to an array on the stack)
I hope that I am clear, I can reformulate if you ask/don't understand a point. Thanks
1: 0x6978616d, 0x6220656d are not addresses, it is the data in your string. When converted to from hex to ascii, 0x6978616d = moht, 0x6220656d = b sa.
2: When used in a function call, arrays decay into pointers. So printf will receive a pointer to char regardless of if c is an array or a pointer.
A compiler may actually choose to compile character array initialisation as a copy from read-only storage, but as Klas suggests, that is not happening in your example.
Here is an example of code for which that does happen (using gcc). It may be illuminating to change the definition of STR to strings of various lengths and look at the difference in assembly output.
/* 99 characters */
#define STR "123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789"
void observe(const char *);
void test1() {
char *str = STR;
observe(str);
}
void test2() {
char str[] = STR;
observe(str);
}
And the assembly:
.section .rodata.str1.4,"aMS",#progbits,1
.align 4
.LC0:
.string "123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789"
.text
test2:
pushl %ebp
movl $25, %ecx
movl %esp, %ebp
subl $136, %esp
movl %esi, -8(%ebp)
movl $.LC0, %esi
movl %edi, -4(%ebp)
leal -108(%ebp), %edi
rep movsl
leal -108(%ebp), %eax
movl %eax, (%esp)
call observe
movl -8(%ebp), %esi
movl -4(%ebp), %edi
movl %ebp, %esp
popl %ebp
ret
test1:
pushl %ebp
movl %esp, %ebp
subl $24, %esp
movl $.LC0, (%esp)
call observe
leave
ret

How do i use arrays in x86 assembly code to replace letters of a word?

Hey everyone so i am working on an assignment involving arrays in assembly. I need to have the user enter a number, then clear the screen. After that a second player tries to guess the word. I did all that but i also have to display a hint everytime the second player tries to guess. For example if i entered the word hello the program displays h!l!o when the second player tries to guess. I have tried it but cant get it to work. Any help would be much appreciated, thank you.
.data
chose:
.ascii "Enter the Secret Word\n"
chose_length:
.int 22
lets_play_response:
.ascii "Try to Guess the Word Entered\n"
l_p_response_length:
.int 30
wrong_guess:
.ascii "Incorrect Guess, Try Again\n"
wrong_guess_length:
.int 27
correct:
.ascii "Correct Guess, Good Job\n"
correct_length:
.int 24
Screen_Clearer:
.ascii "\x1B[H\x1B[2J"
Screen_Clearer_length:
.int 11
letter:
.space 15
guess:
.space 15
.text
.global _start
_start:
mov $chose, %ecx
mov chose_length, %edx
mov $4, %eax
mov $1, %ebx
int $0x80
mov $letter, %ecx
mov $15, %edx
mov $3, %eax
mov $0, %ebx
int $0x80
call Screen_Clear
mov $lets_play_response, %ecx
mov l_p_response_length, %edx
mov $4, %eax
mov $1, %ebx
int $0x80
# Method to Print Word With Every Second Letter Replaced With !
# This is the area with the problems everything else works
mov $0, %edi
Loop:
cmp $4, %edi
jg End
mov $33, letter (%edi)
add $1, %edi
jmp Loop
End:
mov $letter, %ecx
mov $4, %eax
mov $1, %ebx
ret
# End of Method
call GuessLoop
mov $1, %eax
int $0x80
GuessLoop:
mov $guess, %ecx
mov $15, %edx
mov $3, %eax
mov $0, %ebx
int $0x80
mov guess, %ecx
mov letter, %edx
cmp %ecx, %edx
jne Incorrect
je Correct
Incorrect:
mov $wrong_guess, %ecx
mov wrong_guess_length, %edx
mov $4, %eax
mov $1, %ebx
int $0x80
jmp GuessLoop
Correct:
mov $correct, %ecx
mov correct_length, %edx
mov $4, %eax
mov $1, %ebx
int $0x80
ret
# Method That Clears the Screen #
Screen_Clear:
mov $Screen_Clearer, %ecx
mov Screen_Clearer_length, %edx
mov $4, %eax
mov $1, %ebx
int $0x80
ret
# End of Method to Clear Screen
If you are going to use Assembly, you will need to learn about Addressing Modes, Addressing Modes on Google
In this sample, I use the [Base + Index] mode. You will need one more variable to hold your hint string. It is not AT&T syntax, but it will give you the idea
%define sys_exit 1
%define sys_write 4
%define sys_read 3
%define stdin 0
%define stdout 1
SECTION .bss
hint resb 15
letter resb 15
leter_len equ $ - letter
SECTION .text
global _start
_start:
mov ecx, letter
mov edx, leter_len
mov ebx, stdin
mov eax, sys_read
int 80H
mov esi, hint
mov edi, letter
xor ecx, ecx
dec eax
.MakeHint:
mov dl, byte [edi + ecx] ; get byte from pointer + index
cmp dl, 10 ; is it linefeed
je .ShowIt
mov byte[esi + ecx], dl ; move byte into hint buffer
inc ecx ; increase index
cmp ecx, eax ; at the end?
je .ShowIt
mov byte[esi + ecx], 33 ; move ! to next index
inc ecx ; increase index
cmp ecx, eax ; at end?
jne .MakeHint
.ShowIt:
mov ecx, hint
mov edx, leter_len
mov ebx, stdout
mov eax, sys_write
int 80H
mov eax, sys_exit
xor ebx, ebx
int 80h

Resources