ustawienie adresu wskaźnika

0

Hey!

Postaram się zacząć przygodę z C od najcięższej strony... programowanie systemowe ;)

int main() {
	unsigned int test;
	asm(
		"movl	%%ebx,	%0" : "=r" (test)
	);
	unsigned int * p = (unsigned int *) test;

	return p[1];
}

Mniej-więcej udało mi się osiągnąć co chciałem:

[akasei@b450m Lotos]$ ./make.sh 
kernel.c:15:21: warning: cast to 'unsigned int *' from smaller integer type 'unsigned int' [-Wint-to-pointer-cast]
        unsigned int * p = (unsigned int *) test;
                           ^~~~~~~~~~~~~~~~~~~~~
1 warning generated.
[akasei@b450m Lotos]$ ndisasm build/main  -b 64 | head
00000000  89D8              mov eax,ebx
00000002  89C0              mov eax,eax
00000004  8B4004            mov eax,[rax+0x4]
00000007  C3                ret
00000008  0000              add [rax],al
0000000A  0000              add [rax],al
0000000C  0000              add [rax],al
0000000E  0000              add [rax],al
00000010  0000              add [rax],al
00000012  0000              add [rax],al

Tylko dlaczego tam jest ta instrukcja?

mov eax,eax

Gdzie zrobiłem błąd, czy można lepiej?

0

@Akasei: Polecam skompilować ten kod z dodatkową flagą gcc-ka "-g" a potem zrobić tak:

objdump -DSl ./a.out

i zobaczyć wtedy jak kompilator przetwarza kod źródłowy na maszynowy.

A co do tego dziwnego mov-a - to jeśli dobrze go skopiowałeś to on robi tyle co NOP, czyli zajmuje czas procesorowi. Na pewno nie było tam jakiegoś nawiasu?
Ja dostaję trochę inny kod wynikowy niż to co podałeś.

0

@vtx Używam clanga.

clang kernel.c -o build/kernel \
	-nostdlib -fomit-frame-pointer -fno-builtin \
	-Wl,--oformat=binary -Wl,-e,0x100000 -Wl,-Ttext,100000 -Wl,-Tdata,0x100000 -Wl,-Tbss,0x100000 \
	-Oz -m64
0

To próbujesz zrobić:

    unsigned int test,*p=&test;

?
Może powiedz co chcesz osiągnąć?

0

@_13th_Dragon: pragnę by wskaźnik p wskazywał na adres fizyczny pamięci znajdujący się w rejestrze EBX.

I pod tym adresem będę się odwoływał do komórek wg. tej struktury...

typedef struct {
	unsigned mode_attributes:16;
	unsigned win_a_attributes:8;
	unsigned win_b_attributes:8;
	unsigned win_granularity:16;
	unsigned win_size:16;
	unsigned win_a_segment:16;
	unsigned win_b_segment:16;
	unsigned win_func_ptr:32;
	unsigned bytes_per_scanline:16;
	unsigned x_resolution:16;
[...]
} kernel_init_video_structure_mode_info_block;
0

Nieznam się więc się wypowiem :)

Czy chodziło ci o coś takiego?

int main() {
    unsigned int test;
    asm (
        "movl   %%ebx,  %0" : "=b" (test)
    );
    unsigned int * p = (unsigned int *) test;

    return p[1];
}

https://godbolt.org/z/174r9he3x

0

Udało się, pobrałem adres przestrzeni pamięci karty graficznej z 4 komórek pod adresem w rejestrze EDX (na podstawie struktury).

@vtx, zapewne tak zrobię (uint16_t, uint32_t) dużo jaśniej mi mówi ile bajtów zajmuje zmienna

[akasei@b450m Lotos]$ ndisasm build/kernel  -b 64 | head
00000000  89D0              mov eax,edx
00000002  8B4028            mov eax,[rax+0x28]
00000005  C3                ret
struct kernel_init_video_structure_mode_info_block {
	uint8_t		mode_attributes;
	uint8_t		win_a_attributes;
	uint8_t		win_b_attributes;
	uint16_t	win_granularity;
	uint16_t	win_size;
	uint16_t	win_a_segment;
	uint16_t	win_b_segment;
	uint32_t	win_func_ptr;
	uint16_t	bytes_per_scanline;
	uint16_t	x_resolution;
	uint16_t	y_resolution;
	uint8_t		x_char_size;
	uint8_t		y_char_size;
	uint8_t		number_of_planes;
	uint8_t		bits_per_pixel;
	uint8_t		number_of_banks;
	uint8_t		memory_model;
	uint8_t		bank_size;
	uint8_t		number_of_image_pages;
	uint8_t		reserved;
	uint8_t		red_mask_size;
	uint8_t		red_field_position;
	uint8_t		green_mask_size;
	uint8_t		green_field_position;
	uint8_t		blue_mask_size;
	uint8_t		blue_field_position;
	uint8_t		rsvd_mask_size;
	uint16_t	direct_color_mode_info;
	uint32_t	physical_base_address;
};

int main() {
	register uint32_t edx;
	struct kernel_init_video_structure_mode_info_block *p;
	asm volatile("" : "=d" (edx));
	p = (uint32_t*) edx;

        return p->physical_base_address;
}
0

Czemu okrężną drogą przez hipotetycznie mniejszą zmienną?
Czemu nie po ludzku?

    struct kernel_init_video_structure_mode_info_block *ptr;
    //asm ("mov %%edx,%0":"=r"(ptr));
    asm volatile("" : "=d" (ptr));
0

Można też w drugą stronę, zamiast w C robić gas assembler, który ci zapisze do zmiennej adres, możesz się odwołać do ebp-4-8 w zależności od architetkury i tam wrzucić te ebx, a to się pojawi w pierwszej zmiennej zadeklarowanej w funkcji.

Albo od razu podawać strukturę jako parametr funkcji w asm, wtedy C kod bez żadnych wstawek asemblera wykonasz.

Chyba C kodu z assemblerem nie ma co mieszać chyba, że wykonujesz jakieś in/out operacje, wtedy nie ma wyjścia C obsługi portów nie obsługuje i pewnych specyficznych operacji jak wczytanie global description table, interrupt table typowych dla procesora tych akurat C nie wspiera bo normalnie to jest nie wykorzystywane, trzeba wstawkę assemblera dodać, sam gas, at wstawek nie lubię nie wiem dlaczego, ale intela składnia jest najlepiej czytelna.

1 użytkowników online, w tym zalogowanych: 0, gości: 1