Я ищу ответ на каждой странице, но не могу его найти. Я изучаю общесетевой синтаксис сборки около двух месяцев и пытаюсь найти способ хранить данные в памяти.
Я знаю, что sys_break:
mov,eax 45
Резервирует память, и у меня есть функциональный макрос, который резервирует 16 КБ памяти:
%macro reserve_mem
mov eax,45
xor ebx,ebx
int 80h
add eax,16384
mov ebx,eax
mov eax,45
int 80h
%endmacro
Я также знаю, что когда вы резервируете байты (resb), слова и т. Д. в разделе .bss небольшие части памяти выделяются этим неинициализированным данным.
Кроме того, есть виртуальная память, к которой можно получить доступ с адресом типа 0x0000, и она затем отображается в ее фактическую ячейку памяти.
Однако моя проблема в том, что я пытаюсь сохранить данные в памяти, но все, что я пытаюсь сделать, заканчивается ошибкой сегментации (дамп ядра), то есть программой, пытающейся получить доступ к памяти, к которой у нее нет доступа. Я пробовал код, такой как ниже.
mov [0x0000],eax
Спасибо вам за помощь.
1 ответ
Вы, кажется, неправильно понимаете концепцию виртуальной памяти. Это похоже на телефонный номер в том, что вы не можете позвонить кому-либо на каждой комбинации примерно из 10 цифр. Вы можете звонить только по тем номерам, которые указаны в телефонной книге. В противном случае вы услышите «Извините, этот номер в настоящее время не обслуживается». Аналогичным образом, только те виртуальные адреса, которые перечислены в таблице страниц каждого процесса (всегда автоматически и прозрачно поддерживаются ОС), действительны для доступа процесса. SEGV - это способ ОС сказать: «Извините, этот виртуальный адрес в настоящее время не обслуживается».
В вашем коде вы разыменовали 0x0000
, но это одно из наименее возможных значений для действующего виртуального адреса. В итоге вы сделали это, потому что выбросили действительный виртуальный адрес, возвращенный системным вызовом brk(2)
(внимательно прочтите man 2 brk
, потому что необработанный системный вызов ведет себя иначе, чем glibc brk
и sbrk
.) Ваш код будет транслироваться на C таким образом (хотя в настоящее время glibc malloc(3)
часто полагается на mmap(2)
, а не на brk(2)
):
void *p = malloc(16384);
int eax = ...;
(void *)0 = eax;
Это явно неправильно, и вы должны сделать что-то вроде этого:
void *p = malloc(16384);
int *p0 = (int *)p + 0;
int *p1 = (int *)p + 1;
int eax = ...;
int ebx = ...; /* it's all up to you which register to use */
*p0 = eax;
*p1 = ebx;
Что должно переводиться в NASM следующим образом:
reserve_mem ; IIRC eax now points to the last
mov ecx, eax ; byte of the newly allocated chunk
sub ecx, 16383 ; set p0 (== p)
mov edx, ecx
add edx, 4 ; set p1; 4 is for sizeof(int)
; ... set whatever value to eax ...
; ... set whatever value to ebx ...
mov [ecx], eax ; *p0 = eax;
mov [edx], ebx ; *p1 = ebx;
Мои знания о программировании на ассемблере ржавеют, и приведенные выше коды могут содержать много ошибок ... но концептуальная часть не должна быть такой неправильной.
Похожие вопросы
Новые вопросы
memory-management
Процесс динамического распределения и освобождения частей физической памяти для того, чтобы отвечать на программные запросы с, по возможности, справедливостью и без голодания среди запрашивающих.
0x0000
? Вы должны получать доступ только к памяти, которая была выделена для вашего процесса, либо статически с помощьюresb
и др., Либо динамически, например,sys_brk
.sys_brk
? Нельзя просто писать по случайным адресам.