ustawienie adresu wskaźnika

ustawienie adresu wskaźnika
Akasei
  • Rejestracja:prawie 11 lat
  • Ostatnio:około 6 godzin
  • Postów:194
0

Hey!

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

Kopiuj
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:

Kopiuj
[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?

Kopiuj
mov eax,eax

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

edytowany 1x, ostatnio: Akasei
VT
  • Rejestracja:ponad 5 lat
  • Ostatnio:prawie 2 lata
0

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

Kopiuj
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ś.

Akasei
  • Rejestracja:prawie 11 lat
  • Ostatnio:około 6 godzin
  • Postów:194
0

@vtx Używam clanga.

Kopiuj
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
_13th_Dragon
  • Rejestracja:ponad 19 lat
  • Ostatnio:2 miesiące
0

To próbujesz zrobić:

Kopiuj
    unsigned int test,*p=&test;

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


Wykonuję programy na zamówienie, pisać na Priv.
Asm/C/C++/Pascal/Delphi/Java/C#/PHP/JS oraz inne języki.
Akasei
Nie, to mi wskaże na komórkę pamięci gdzie znajduje się wartość z rejestru EBX jak dobrze już rozumiem ;)
Akasei
  • Rejestracja:prawie 11 lat
  • Ostatnio:około 6 godzin
  • Postów:194
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...

Kopiuj
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;
edytowany 2x, ostatnio: Akasei
Zobacz pozostałe 4 komentarze
Akasei
Nie ważne czy będzie to adres logiczny czy fizyczny... obydwa wskazują na tą samą przestrzeń, gdyż tak skonfigurowałem stronicowanie w programie rozruchowym.
VT
Ok, czyli masz mapowanie 1:1. Tak się zastanawiam czy ten dziwny mov to nie jest jakieś wyrównanie (alignment)... Sorki, nie wszyskto już pamiętam z ix86.
Akasei
Może być, ale z innej beczki... da się zainicjować wskaźnik tak jak potrzebuje w jednej linijce kodu?
AL
@Akasei: a może to Ci pomoże. Inna architektura, teoretycznie (chyba) UB, w praktyce działa: https://github.com/espruino/Espruino/blob/master/targetlibs/stm32f1/lib/stm32f10x.h#L1400 EDIT: bo rozumiem, że po prostu chcesz fragment pamięci "zmapować" na pola Twojego structa; Jedna rzecz: __attribute__((packed)) albo podobny nie będzie Ci tu potrzebny?
VT
@Akasei jeśli możesz używaj uint16_t, uint32_t etc zamiast unsigned int
plx211
  • Rejestracja:około 11 lat
  • Ostatnio:2 miesiące
  • Postów:181
0

Nieznam się więc się wypowiem :)

Czy chodziło ci o coś takiego?

Kopiuj
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

Akasei
Ten "lepszy" kod dostałem na kanale Discord "register uint32_t edx; asm volatile("" : "=d" (edx));", ale bardzo dziękować ;)
plx211
ogólnie z tego co wyczytałem to przez =b wybierasz który rejestr chcesz, więc =a to EAX, ..., =b to EBX, ..., =c to ... :)
Akasei
@plx211: Już wywnioskowałem ortoleptycznie :)
Akasei
  • Rejestracja:prawie 11 lat
  • Ostatnio:około 6 godzin
  • Postów:194
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

Kopiuj
[akasei@b450m Lotos]$ ndisasm build/kernel  -b 64 | head
00000000  89D0              mov eax,edx
00000002  8B4028            mov eax,[rax+0x28]
00000005  C3                ret
Kopiuj
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;
}
edytowany 1x, ostatnio: Akasei
_13th_Dragon
  • Rejestracja:ponad 19 lat
  • Ostatnio:2 miesiące
0

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

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

Wykonuję programy na zamówienie, pisać na Priv.
Asm/C/C++/Pascal/Delphi/Java/C#/PHP/JS oraz inne języki.
edytowany 1x, ostatnio: _13th_Dragon
Akasei
No widzisz :) Ja nie umiem programować w C ;) Własnie się uczę.
_13th_Dragon
Ależ ty nawet nie próbujesz uczysz się c++ ty próbujesz uczyć się nakładki dla jednego z assemblerów w wykonaniu jednego z producentów. Wg mnie powinno być to co w komentarzu, ale skoro ponieważ to asm volatile("" : "=d" (edx)); to działa to na 100% będzie działać i to co bez komentarza.
Szalony Programista
Szalony Programista
  • Rejestracja:około 7 lat
  • Ostatnio:prawie 4 lata
  • Postów:227
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.

edytowany 3x, ostatnio: Szalony Programista
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)