I have got some problem with memory access and postix incrementation :/
I need to access to video memory at boot, thus, I create a pointer to 0xB8000 address and then, I increment the pointer to access next location.
Basically, the code would be :
volatile char *p = (volatile char *)0xB8000;
for (int i = 0; i < 5; ++i)
*(p++) = 'A';
This way, p point to the proper memory address, and after each access, it is incremented (I know, the there is 2 bytes for each character displayed, but here is not the problem).
But this doesn't work, no character displayed. It display nothing. But if I change incrementation to prefix like this, it works, i can see the characters on the screen !
volatile char *p = (volatile char *)0xB8000;
for (int i = 0; i < 5; ++i)
*(++p) = 'A'
So, I checked assembly code :
; Postfix
mov ecx, DWORD PTR _p$[ebp]
mov BYTE PTR [ecx], 65 ; 'A' character
mov edx, DWORD PTR _p$[ebp]
add edx, 1
mov DWORD PTR _p$[ebp], edx
; Prefix
mov ecx, DWORD PTR _p$[ebp]
add ecx, 1
mov DWORD PTR _p$[ebp], ecx
mov edx, DWORD PTR _p$[ebp]
mov BYTE PTR [edx], 65 ; 'A' character
I can't spot the difference. By the way, I could use the prefix incrementation but, I would like to understand with does the postfix not work :/
The assembly code is from Visual C++ compiler, I don't have any GCC at work :/
EDIT : I know the difference between prefix and postfix incrementation, and I see the difference between assembly code present here. But IMO, none of these differences leads to non printing characters on screen.
About the attribute byte : I know I should set it properly. I would keep a light example with light assembly code, but actually, with incrementation the attribute character is always set to 'A' wich lead to a blue letter on a red background.
Thank you :)
After a few more tests, I found the possible cause of this error, it was about the .rodata section not properly linked, so it's now better.
For more details, I follow some of the instructions availables on an OSDev Tutorial ;)
Related
I want to write a function in x86 which will be called from C program.
The function should look like this:
char *remnth(char *s, int n);
I want it to remove every nth letter from string s and return that string. Here's my remnth.s file:
section.text
global remnth
remnth:
; prolog
push ebp
mov ebp, esp
; procedure
mov eax, [ebp+8]; Text in which I'm removing every nth letter
mov ebx, [ebp+12]; = n
mov ecx, [ebp+8] ; pointer to next letter (replacement)
lopext:
mov edi, [ebp+12] ; edi = n //setting counter
dec edi ; edi-- //we don't go form 'n' to '1' but from 'n-1' to '0'
lop1:
mov cl, [ecx] ; letter which will be a replacement
mov byte [eax], cl ; replace
test cl,cl ; was the replacement equal to 0?
je exit ; if yes that means the function is over
inc eax ; else increment pointer to letter which will be replaced
inc ecx ; increment pointer to letter which is a replacement
dec edi ; is it already nth number?
jne lop1 ; if not then repeat the loop
inc ecx ; else skip that letter by proceeding to the next one
jmp lopext ; we need to set counter (edi) once more
exit:
; epilog
pop ebp
ret
The problem is that when I'm calling this function from main() in C I get Segmentation fault (core dumped)
From what I know this is highly related to pointers, in this case I'm returning *char, and since I've seen some functions that returns int and they worked just fine, I suspect that I forgot about something important with returning a *char properly.
This is what my C file looks like:
#include <stdio.h>
extern char *remnth(char *s,int n);
int main()
{
char txt[] = "some example text\0";
printf("orginal = %s\n",txt);
printf("after = %s\n",remnth(txt,3));
return 0;
}
Any help will be appreciated.
You're using ecx as a pointer, and cl as a work register. Since cl is the low 8 bits of ecx, you're corrupting your pointer with the mov cl, [ecx] instruction. You'll need to change one or the other. Typically, al/ax/eax/rax is used for a temporary work register, as some accesses to the accumulator use shorter instruction sequences. If you use al as a work register, you'll want to avoid using eax as a pointer and use a different register instead (remembering to preserve its contents if necessary).
You need to load the return value into eax before the return. I assume you want to return a pointer to the beginning of the string, so that would be [ebp+8].
I am completing an assignment related to c programming and assembly language. Here is the simple c program :
int multiply(int a, int b) {
int k = 4;
int c,d, e;
c = a*b ;
d = a*b + k*c;
return d;
}
And it's optimised assembly is
_a$ = 8 ; size = 4
_b$ = 12 ; size = 4
_multiply PROC
mov eax, DWORD PTR _a$[esp-4]
imul eax, DWORD PTR _b$[esp-4]
lea eax, DWORD PTR [eax+eax*4]
ret 0
_multiply ENDP
I want to know the value of eax register after this line of code in assembly
lea eax, DWORD PTR [eax+eax*4]
I know when add integers in assembly, it stores result in the destination. and when we multiply it stores in eax. so if I call the function multiply( 3 , 8 ), the value of eax register after that line should be 120. Am I correct?
lea is "load effective address".
Instruction sets can have some quite complex multi-register address calculation modes that are generally used just for reading and writing data to memory, but lea allows the programmer to get the address that would be accessed by the instruction.
Effectively, it performs the calculation inside the bracket, returns that value - it doesn't access the memory (which is what bracket usually implies).
In this case it is being used as a quick way to multiply by 5, because the rest of the function has been optimised away!
This question already has answers here:
How to initialize all members of an array to the same value?
(26 answers)
Closed 4 years ago.
When I intialize a string:
char pol[100];
and printf it, I get this weird ╠ sign 100 times.
My question is how to intialize a string, print it and get only blanks?
Thanks!
╠ is a character with code 0xCC in the OEM 850 codepage.
In debug builds, Visual C initializes uninitialized data with 0xCC to help you detect uninitialized data.
You should initialize the array.
char pol[100] = {0};
or
char pol[100] = "test data";
You can do that with:
char pol[100];
pol[0] = '\0';
First characters will be a null character.
If you want all of your array: char pol[100] = {0};
Test this way:
char test[100] = { 0 };
for (int i = 0; i < 100; i++)
printf("%c ", test[i]);
You can see the assembly here:
For x86 old compilers, that will be generate like:
push 100
push 0
lea eax, DWORD PTR _teste$[ebp]
push eax
call _memset
add esp, 12
On newer:
lea rdx, [rbp-112]
mov eax, 0
mov ecx, 12
mov rdi, rdx
rep stosq
mov rdx, rdi
mov DWORD PTR [rdx], eax
add rdx, 4
Test it on Godbolt.org selecting apropriate compiler
When I intialize a string:...
The variable pol has not been initialized, only declared, and as such, because of the definition of C string, may or may not even be a string at this point. Using it in this state (eg. in a printf() statement) is dangerous as it can invoke undefined behavior.
Change this:
char pol[100];
to This
char pol[100] = {0};//initializes entire array to `0`.
or this for example:
char pol[100] = {"temporary"};//initializes to |t|e|m|p|o|r|a|r|y|0|?|?|?|?|
//which is a null terminated string
mov rax,QWORD PTR [rbp-0x10]
mov eax,DWORD PTR [rax]
add eax,0x1
mov DWORD PTR [rbp-0x14], eax
Next lines written in C, compiled with GCC in GNU/Linux environment.
Assembly code is for int b = *a + 1;.
...
int a = 5;
int* ptr = &a;
int b = *a + 1;
dereferencing whats in address of a and adding 1 to that. After that, store under new variable.
What I don`t understand is second line in that assembly code. Does it mean that I cut QWORD to get the DWORD(one part of QWORD) and storing that into eax?
Since the code is few lines long, I would love that to be broke into step by step sections just to confirm that I`m on right track, also, to figure out what that second line does. Thank you.
What I don`t understand is second line in that assembly code. Does it mean that I cut QWORD to get the DWORD(one part of QWORD) and storing that into eax?
No, the 2nd line dereferences it. There's no splitting up of a qword into two dword halves. (Writing EAX zeros the upper 32 bits of RAX).
It just happens to use the same register that it was using for the pointer, because it doesn't need the pointer anymore.
Compile with optimizations enabled; it's much easier to see what's happening if gcc isn't storing/reloading all the time. (How to remove "noise" from GCC/clang assembly output?)
int foo(int *ptr) {
return *ptr + 1;
}
mov eax, DWORD PTR [rdi]
add eax, 1
ret
(On Godbolt)
int a = 5;
int* ptr = &a;
int b = *a + 1;
your example is an undefined behaviour as you dereference the integer value converted to the pointer (in this case 5) and it will not compile at all as this conversion has the unknown type.
To make it work you need to cast it first.
`int b = *(int *)a + 1;
https://godbolt.org/g/Yo8dd1
Explanation of your assembly code:
line 1: loads rax with the value of a (in this case 5)
line 2: dereferences this value (reads from the address 5 so probably you will get the segmentation fault). this code loads from the stack only because you use the -O0 option.
I been debugging REP STOS DWORD PTR ES:[EDI] for a while now
From my conclusion it always uses
ECX as counter.
EAX as the value that will be copied over EDI and then appended ECX times
so after putting in the pointed dump of EDI
it seems to overwrite the pointed data at EDI with what's
it seems it always only uses ECX as a counter, while changing EDI by 4 bytes.
it stops working when counter hits 0
So I came up with this kind of code
while(regs.d.ecx != 0)
{
*(unsigned int *)(regs.d.edi) = regs.d.eax;
regs.d.edi += 4;
regs.d.ecx--;
}
Seems to work.. but i'm concerned since I just did this by luck and guess work. Is it solid? like will it always be ECX as counter, EAX as data, and it always copies 4 bytes never less?
You are almost correct. The only difference is that the direction flag (DF) controls whether 4 is added or subtracted from EDI (and it actually is offset from the ES segment base, but you probably don't care about that):
for (; regs.d.ecx != 0; regs.d.ecx--)
{
*(unsigned int *)(regs.d.edi) = regs.d.eax;
regs.d.edi += regs.eflags.df ? -4 : 4;
}
Note that the for (; regs.d.ecx != 0; regs.d.ecx--) { } is the action of the REP prefix, and the body of the loop is the action of STOS DWORD....
Since you are asking a lot of these questions, I think you will find the Intel 64 and IA-32 Architectures Software Developer’s Manual, Volumes 2A and 2B to be useful. These contain descriptions of each instruction and prefix, including pseudo-code descriptions.