Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Низкоуровневое программирование > Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM
Регистрация

Восстановить пароль

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 17.03.2024, 18:01   #1
iXNomad
Пользователь
 
Регистрация: 06.01.2021
Сообщений: 52
По умолчанию Гоу все учить ассемблер, мне нравится)

Примерно что я услышал у одного англоязычного (как я понял, из США) программиста. Идея в том, что понимание того, как компьютер устроен "под капотом" помогает нам, как программистам, принимать более правильные, лучшие решения, т.к. это помогает нам понимать, почему одни вещи медленнее других.
Я его идею понял так: само понимание того, как всё работает на уровне архитектуры компьютера (не обязательно быть экспертом ассемблера) приводит к тому, что, программируя на каком-то более высокоуровневом языке, мы будем чаще принимать правильные решения с точки зрения производительности/потребления памяти, что упростит разработку в целом. Как-бы мы начинаем видеть, почему что-то работает медленно, и вообще почему это написано плохо.

Вот моя первая прога, в двух вариантах (32 и 64-bit на Linux).
cpuid работает так: если в аккумуляторе у нас 0, то тогда он нам выдаёт информацию о производителе процессора в виде 12 байт кодов ASCII в такой последовательности регистров: ebx:edx:ecx
Для того, чтобы получить полное название своего процессора, надо положить в eax число от 0x80000002 до 0x80000004 и с каждым этим числов вызывать cpuid, эта команда положит нам последовательное в регистры eax:ebx:ecx:edx часть 48-байтной строки, а именно по 4 байта (размер регистров) в каждый из 4х регистров, т.е. по 16 кодов ASCII. Мы их запишем в заранее зарезервированную память.
[SPOILER=]
Код:
; mycpuname.asm (17/03/2024)

section .bss
cpuname resb 49 ; резервируем 49 байт

section .text
        global _start

_start:
        xor eax, eax        
        cpuid

        mov [cpuname], ebx
        mov [cpuname + 4], edx
        mov [cpuname + 8], ecx
        mov [cpuname + 12], byte 10 ; 10 - это символ \n

        mov eax, 4
        mov ebx, 1
        mov ecx, cpuname
        mov edx, 13
        int 0x80

        xor edi, edi
regcpy:        
        mov eax, 0x80000002
        mov esi, edi
        shr esi, 4
        add eax, esi
        cpuid
        mov [cpuname + edi], eax
        mov [cpuname + 4 + edi], ebx
        mov [cpuname + 8 + edi], ecx
        mov [cpuname + 12 + edi], edx
        add edi, 16
        cmp edi, 48
        jne regcpy

        mov [cpuname + 48], byte 10 ; 49й символ для \n - это нужно +48, т.к. если 0 то это первый

        mov eax, 4 ; номер системного вызова sys_write
        mov ebx, 1 ; 1 это стандартный поток вывода
        mov ecx, cpuname ; адрес откуда ОС будет выводить символы
        mov edx, 49 ; сколько символов, тут главное не получить segfault
        int 0x80

        mov eax, 1
        xor ebx, ebx
        int 0x80
Компилируем в executable linkable format 32, "-g" можно убрать, это для gdb:
Код:
$nasm -f elf32 -o mycpuname.o mycpuname.asm -g
Собираем:
Код:
$ld -m elf_i386 -o mycpuname mycpuname.o -g
И для 64-битного варианта. Таблица системных вызовов для 64-бит отличается. Если не проверить и не изменить, то у меня вот Segmentation Fault вылетел.
Код:
; mycpuname64.asm (17/03/2024)

section .bss
cpuname resb 49

section .text
        global _start

_start:
        xor rax, rax        
        cpuid

        mov [cpuname], ebx
        mov [cpuname + 4], edx
        mov [cpuname + 8], ecx
        mov [cpuname + 12], byte 10

        mov rax, 1
        mov rdi, 1
        mov rsi, cpuname
        mov rdx, 13
        syscall

        xor edi, edi
regcpy:        
        mov eax, 0x80000002
        mov esi, edi
        shr esi, 4
        add eax, esi
        cpuid
        mov [cpuname + edi], eax
        mov [cpuname + 4 + edi], ebx
        mov [cpuname + 8 + edi], ecx
        mov [cpuname + 12 + edi], edx
        add edi, 16
        cmp edi, 48
        jne regcpy

        mov [cpuname + 48], byte 10

        mov rax, 1
        mov rdi, 1
        mov rsi, cpuname
        mov rdx, 49
        syscall

        mov rax, 60
        xor rbx, rbx
        syscall
Компилируем в executable linkable format 64:
Код:
$nasm -f elf64 -o mycpuname64.o mycpuname64.asm -g
Собираем:
Код:
$ld -m elf_x86_64 -o mycpuname64 mycpuname64.o -g
[/SPOILER]

У меня тут мб ещё куча ошибок, но это можно сказать первая прога не считая всякого баловства с с регистрами и хеллоу ворлдами. Ещё мало чего понимаю, но мне жуть как интересно

Интересно дебажить, gdb тоже классная штука:
Запускаем:
Код:
$gdb mycpuname
Для удобства можно сделать так:
Код:
layout asm
или
Код:
layout src
Можно смотреть исходник. Это всё работает, если мы компилируем с флагом -g.
Код:
layout reg // смотрим регистры
break _start // добавляем брейкпоинт на метке _start
run // запускаем программу, вводим ещё раз = запускаем заново
n // следующий шаг, прям следующая инструкция
x/s &cpuname // тут можно отслеживать что у нас, /s значит что отображаем всю строку, логично, что меняется это после системного вызова int 0x80 (тут int значит не integer а interrupt, я только недавно узнал) или syscall
q //выходим
Заметил странную вещь: если я резервирую в resb не 49, а меньше, то всё работает нормально (СТРАННО, я вот ВООБЩЕ пока не понял этого), но если пишу cpuname resb 0, то получаю segmentation fault.
iXNomad вне форума Ответить с цитированием
Старый 17.03.2024, 19:21   #2
Steelcraft
Форумчанин
 
Регистрация: 13.03.2023
Сообщений: 113
По умолчанию

Этот англоязычный программист забыл одну важную вещь: архитектур компьютера существует больше одной. На одном x86/x64 свет клином не сошелся. И при смене архитектуры все эти ассемблерные игры превращаются в тыкву.

И еще вторую важную вещь: современные оптимизирующие компиляторы учитывают возможности процессора гораздо лучше, чем среднестатистический кодер. Важно только не мешать их работе, например, не заниматься преждевременной "оптимизацией" кода. Поэтому хорошее знание стандарта языка более важно.

Знание ассемблера тоже не помешает, но оно полезнее при отладке некоторых тонких ситуаций на низком уровне.
Steelcraft вне форума Ответить с цитированием
Старый 17.03.2024, 20:57   #3
iXNomad
Пользователь
 
Регистрация: 06.01.2021
Сообщений: 52
По умолчанию

Цитата:
Сообщение от Steelcraft Посмотреть сообщение
Этот англоязычный программист забыл одну важную вещь: архитектур компьютера существует больше одной. На одном x86/x64 свет клином не сошелся. И при смене архитектуры все эти ассемблерные игры превращаются в тыкву.
Уверен он имел в виду именно понимание общих принципов работы CPU на таком низком уровне.
В одной книге находил интересную мысль, суть в том, что программист, не представляющий, как там всё работает хотя бы примерно, просто не понимает, что он на самом деле делает, когда пишет на высокоуровневом языке.

Я вот не совсем понимаю, почему, когда я уменьшаю выделенную память с 49 байт на меньшее число, то оно не segfault'ится пока я не выделю 0.

Последний раз редактировалось iXNomad; 17.03.2024 в 21:00.
iXNomad вне форума Ответить с цитированием
Старый 17.03.2024, 21:11   #4
Vapaamies
Просветитель
Участник клуба
 
Аватар для Vapaamies
 
Регистрация: 26.12.2012
Сообщений: 1,844
По умолчанию

Цитата:
Сообщение от iXNomad Посмотреть сообщение
Я вот не совсем понимаю, почему, когда я уменьшаю выделенную память с 49 байт на меньшее число, то оно не segfault'ится пока я не выделю 0.
Работает выравнивание секций PE. Одного ассемблера мало, надо еще знать теорию ОС.

Ой, это Linux. С форматом ELF не знаком, но предполагаю, что там нечто похожее. 1000h — 4096 байта, как раз размер страницы. Меньше не может быть выделено, если секции не объединяются.

Последний раз редактировалось Vapaamies; 17.03.2024 в 21:13.
Vapaamies вне форума Ответить с цитированием
Старый 17.03.2024, 21:41   #5
iXNomad
Пользователь
 
Регистрация: 06.01.2021
Сообщений: 52
По умолчанию

Цитата:
Сообщение от Vapaamies Посмотреть сообщение
Работает выравнивание секций PE. Одного ассемблера мало, надо еще знать теорию ОС.

Ой, это Linux. С форматом ELF не знаком, но предполагаю, что там нечто похожее. 1000h — 4096 байта, как раз размер страницы. Меньше не может быть выделено, если секции не объединяются.
Я слышал, мне тут в одной теме писали, что выделяется как минимум страница сразу.
Т.е. если я выделяю 1 или больше байтов, ОС мне даёт сразу целую пачку?
А почему тогда если я пытаюсь сделать что-то такое (записать/напечатать больше, чем есть места) в C, вылезти хоть на 1 байт, у меня обычно стабильный segfault?

Цитата:
Сообщение от Vapaamies Посмотреть сообщение
Одного ассемблера мало, надо еще знать теорию ОС.
Судя по всему, логика курса МГУ действительно правильная. Основы программирования (Pascal) - Архитектура ПК (ASM) - ОС (C)

Последний раз редактировалось iXNomad; 17.03.2024 в 21:45.
iXNomad вне форума Ответить с цитированием
Старый 17.03.2024, 22:04   #6
Vapaamies
Просветитель
Участник клуба
 
Аватар для Vapaamies
 
Регистрация: 26.12.2012
Сообщений: 1,844
По умолчанию

Цитата:
Сообщение от iXNomad Посмотреть сообщение
А почему тогда если я пытаюсь сделать что-то такое (записать/напечатать больше, чем есть места) в C, вылезти хоть на 1 байт, у меня обычно стабильный segfault?
В Си, если не брать жесткую встроенку, память выделяется через менеджер кучи, работающий поверх страничного механизма ОС. Вот в KolibriOS, например, так и не сделали системный менеджер кучи, и программам или приходится городить доморощенный, или выделять по странице при каждом вызове malloc(). Каково?
Vapaamies вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Что вам нравится и не нравится в вашей профессии? Illusiony Свободное общение 17 07.12.2018 21:22
Начал учить Ассемблер и запутался Andrey2011a Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM 4 24.09.2011 23:37
php не нравится del ilushka2306 PHP 3 08.05.2011 15:16
Не понятно что ему не нравится _ILYA_ Visual C++ 3 29.10.2010 20:25
Чем вам не нравится Delphi? docbrain Свободное общение 116 16.10.2010 10:18