Intereting Posts

Вставка значений в массив и отображение, nasm

Прежде всего, это домашнее задание.

У меня есть цикл, чтобы получить значения двух цифр по отдельности и присоединяя их, делая умножение первой цифры на 10 и добавляя вторую цифру, чтобы получить целое число.

Я делаю все это и сохраняю в своем регистре AL , и теперь я хочу вставить это целое число в массив, а затем сканировать этот массив и отображать эти числа.

Как я могу вставлять в вектор и читать из вектора?

Мой массив:

 section .bss array resb 200 

Моя цифра конвертирует:

 sub byte[digit_une], 30h sub byte[digit_two], 30h mov al, byte[digit_one] mov dl, 10 ;dl = 10 mul dl ;al = ax = 10 * digit_one add al, byte[digit_two] ;al = al + digit_two = digit_one * 10 + digit_two 

Related of "Вставка значений в массив и отображение, nasm"

«массивы», «векторы» и т. д. – все это концепция более высокого уровня. Машина имеет память, которая адресуется одним байтом, и какую логику вы реализуете с помощью своего кода, это зависит от вас. Но вы должны уметь думать об этом на обоих уровнях, как одинарные байты в памяти, каждый из которых имеет свой собственный адрес и полностью понимает вашу логику кода, как он будет организовывать использование этих байтов для формирования «массива чего-то».

С вашим определением сектора .bss вы определяете один array символов / меток, который равен адресу в памяти, где начинается сегмент .bss . Затем вы резервируете 200 байт пространства, поэтому все остальное, что вы добавите после (например, другой метки), начнется с адреса .bss+200 .

Скажем, например, после загрузки вашего двоичного кода в память и перехода к точке входа .bss находится по адресу 0x1000 .

затем

 mov dword [array],0x12345678 

будет хранить 4 байта в памяти по адресам 0x1000 .. 0x1003 , с конкретными байтами, имеющими значения 78 56 34 12 (мало-дневная разбивка этого значения слова).

Если вы сделаете mov dword [array+199],0x12345678 , вы будете записывать значение 0x78 в последний официально зарезервированный байт с помощью этого resb 200 , а оставшиеся 3 байта будут перезаписывать память по адресам .bss + 200, .bss + 201 и .bss + 202 (возможно, повреждение некоторых других данных, если вы поместите что-то там или сбой приложения, если он пересечет границу страницы памяти, и вы находитесь в конце доступной памяти для вашего процесса).

Поскольку вы хотите хранить N байтов в массиве, простейшая логика заключается в том, чтобы сохранить первое значение в array+0 адресов array+0 , второе в array+1 и т. Д. (Для значений dword наиболее логичным способом является array+0, array+4, array+8, .... ).

т.е. mov [array+0],al может использоваться для хранения первого значения. Но это не очень практично, если вы читаете ввод в каком-то цикле. Предположим, вы хотите прочитать не более 200 значений от пользователя, или значение 99 закончится раньше, тогда вы можете использовать индексирование по регистру, например:

  xor esi,esi ; rsi = index = 0 mov ecx,200 ; rcx = 200 (max inputs) input_loop: ; do input into AL = 0..99 integer (preserve RSI and RCX!) ... cmp al,99 je input_loop_terminate mov [array+rsi], al ; store the new value into array inc rsi ; ++index dec rcx ; --counter jnz input_loop ; loop until counter is zero input_loop_terminate: ; here RSI contains number of inputted values ; and memory from address array contains byte values (w/o the 99) 

Т.е. для пользовательских ввода 32, 72, 13, 0, 16, 99 память по адресу 0x1000 будет иметь 5 байтов, которые будут содержать (в гекса) сейчас: 20 48 0D 00 10 ?? ?? ?? ... 20 48 0D 00 10 ?? ?? ?? ... 20 48 0D 00 10 ?? ?? ?? ...

Если вы несколько опытный программист asm, вы не только индексируете по регистру, но также избегаете ярлыка жестко заданного array , поэтому вы, вероятно, будете выполнять подпрограмму, которая принимает в качестве аргумента целевой адрес (массива) и максимальный счетчик:

 ; function to read user input, rsi = array address, rcx = max count ; does modify many other registers ; returns amount of inputted values in rax take_some_byte_values_from_user: jrcxz .error_zero_max_count ; validate count argument lea rdi,[rsi+rcx] ; rdi = address of first byte beyond buffer neg rcx ; rcx = -count (!) ; ^ small trick to make counter work also as index ; the index values will be: -200, -199, -198, ... ; and that's perfect for that "address of byte beyond buffer" .input_loop: ; do input into AL = 0..99 integer (preserve RSI, RDI and RCX!) ... cmp al,99 je .input_loop_terminate mov [rdi+rcx], al ; store the new value into array inc rcx ; ++counter (and index) jnz .input_loop ; loop until counter is zero .input_loop_terminate: ; calculate inputted size into RAX lea rax,[rdi+rcx] ; address beyond last written value sub rax,rsi ; rax = count of inputted values ret .error_zero_max_count: xor eax,eax ; rax = 0, zero values were read ret 

Затем вы можете вызвать эту подпрограмму из основного кода следующим образом:

  ... mov rsi,array ; rsi = address of reserved memory for data mov ecx,200 ; rcx = max values count call take_some_byte_values_from_user ; keep RAX (array.length = "0..200" value) somewhere test al,al ; as 200 was max, testing only 8 bits is OK jz no_input_from_user ; zero values were entered ... 

Для массивов элементов word / dword / qword x86 имеет коэффициент масштабирования в операнде памяти, поэтому вы можете использовать значение индекса, равное +1, а значение адреса равно:

  mov [array+4*rsi],eax ; store dword value into "array[rsi]" 

Для других элементов обычно лучше иметь указатель вместо индекса и переходить к следующему элементу, add , например add rdi,96 , чтобы избежать умножения значения индекса для каждого доступа.

и т. д. значения чтения обратно работают одинаково, но наоборот.

Кстати, этот пример не столько «вставляет» значения в массив, сколько «перезаписывает» его. Компьютерная память уже существует и имеет некоторые значения ( .bss обнуляется libc или OS IIRC? В противном случае может существовать какой-то мусор), поэтому он просто перезаписывает старые значения нежелательной почты со значениями от пользователя. По-прежнему сохраняется 200 байтов памяти «зарезервировано» с помощью resb , и ваш код должен отслеживать реальный размер (количество введенных значений), чтобы знать, где заканчивается ввод пользователя, и где начинаются данные мусора (или вы можете в конечном итоге записать значение 99 в массив тоже, и использовать это как значение «terminator», тогда вам нужен только адрес массива для сканирования его содержимого и остановки при обнаружении значения 99 ).

РЕДАКТИРОВАТЬ:

И на всякий случай вы все еще задаетесь вопросом, почему я иногда использую квадратные скобки, а иногда нет, этот Q + A выглядит достаточно подробно, а синтаксис YASM аналогичен синтаксису NASM в скобках: основное использование непосредственных (квадратных скобок) в x86. Сборка и ясность