winapi – Вызвать функцию GetSystemInfo через ассемблер – Stack Overflow на русском

Getsysteminfo doesn’t work

I’m trying to determine if the current system is 32 or 64 bit. And I want to get that info from the SystemInfo, but it VS gives me error’s when I try to compile this. I can’t use most other methods to determine if the OS is 64 or 32 bit. Because I need to check if windows is 64 bit and not the process.

LPSYSTEM_INFO info;
GetSystemInfo(&info); // Error

IntelliSense: argument of type “LPSYSTEM_INFO *” is incompatible with parameter of type “LPSYSTEM_INFO”

error C2664: ‘GetSystemInfo’ : cannot convert parameter 1 from ‘LPSYSTEM_INFO *’ to ‘LPSYSTEM_INFO’

Вызвать функцию getsysteminfo через ассемблер

DISCLAIMER:

Нет никакого смысла писать этот код на ассемблере, все то же самое
намного проще было бы написать на Си (в конце пример).

Насколько возможно минимальный пример на fasm, результат – 32-битный консольный exe файл:

format PE CONSOLE
entry start
include 'win32a.inc'
section '.text' code readable executable start: invoke GetSystemInfo, system_info ; dword перед [system_info.wProcessorArchitecture] нужно из-за того что это 2-байтовое поле (word), ; его нельзя просто так передать с помощью push. ; dword здесь приводит к тому, что по адресу поля читается 4 байта вместо 2. ; Но это корректно работает только потому, что после этого поля идет зарезервированное пустое 2-байтовое поле ; (если бы было не пустое, вывелось бы неправильное значение) cinvoke printf, format_string, dword [system_info.wProcessorArchitecture], [system_info.dwPageSize] invoke getch ; ожидание нажатия клавиши перед завершением, можно и без этого, если запускаете из командной строки invoke ExitProcess,0
section '.data' data readable writeable
system_info SYSTEM_INFO
format_string: db 'wProcessorArchitecture: %d', 0x0d, 0x0a db 'dwPageSize: %d', 0x0d, 0x0a, 0
section '.idata' import data readable writeable
library kernel32, 'KERNEL32.DLL', msvcrt, 'MSVCRT.DLL'
include 'api/kernel32.inc'
import msvcrt, printf,'printf', getch,'_getch'
section '.reloc' fixups data readable discardable

Тут для примера вывод значений только первых двух полей – wProcessorArchitecture и dwPageSize.

В 32-битной версии выводит:

wProcessorArchitecture: 0
dwPageSize: 4096

0 соответствует PROCESSOR_ARCHITECTURE_INTEL, см. описание структуры SYSTEM_INFO

Если изменить в коде PE на PE64 и include 'win32a.inc' на include 'win64a.inc', получится 64-битный экзешник, вывод будет такой:

wProcessorArchitecture: 9
dwPageSize: 4096

9 соответствует PROCESSOR_ARCHITECTURE_AMD64.

“Магическая” строка system_info SYSTEM_INFO – это макрос, который при компиляции разворачивается в набор полей соответствующей структуры, например для 32-битного экзешника (взято из файла fasm/include/equates/kernel32.inc):

struct SYSTEM_INFO wProcessorArchitecture dw ? wReserved dw ? dwPageSize dd ? lpMinimumApplicationAddress dd ? lpMaximumApplicationAddress dd ? dwActiveProcessorMask dd ? dwNumberOfProcessors dd ? dwProcessorType dd ? dwAllocationGranularity dd ? wProcessorLevel dw ? wProcessorRevision dw ?
ends

Для 64-битной версии все то же самое, только размеры полей-указателей (те, что начинаются на lp) другие – 64-битные (dq) вместо 32-битных (dd).

:/>  Как включить просмотр фотографий в Windows 10 |

Также нужно сказать, что invoke, cinvoke – это макросы, которые при компиляции превращаются в разный код в зависимости от подключенного в начале программы файла – win32a.inc или win64a.inc.

Для 32-битной версии invoke превращается в 0 или более push, и call в конце – соглашение stdcall. Для cinvoke порядок push противоположный, и после call еще выравнивается стек на размер переданных через push параметров – соглашение cdecl (используется для функций с переменным числом параметров, как у того же printf). См. Соглашения о вызовах, используемые на x86 при 32-битной адресации.

Для 64-битной версии все несколько сложнее, можете для ознакомления посмотреть здесь: Соглашение о вызовах для 64-разрядных систем


P.S. более-менее эквивалентный код на Си:

include <windows.h>
include <stdio.h>
SYSTEM_INFO system_info;
int main() { GetSystemInfo(&system_info); printf("wProcessorArchitecture: %dn" "dwPageSize: %dn", system_info.wProcessorArchitecture, system_info.dwPageSize); // Тут мог быть вызов getch();, но эта функция не входит в стандарт, поэтому не добавляю return 0;
}

Примечания:

Автор вовсе не стремится каким-либо образом дополнить существующие коммерческие продукты, а также продукты с открытым исходным кодом, в которых предоставляются полные наборы утилит UNIX. Хотя приводимые примеры и могут найти практическое применение, они предназначены, главным образом, для того, чтобы продемонстрировать возможности функций Windows.

Цены на модули памяти постоянно снижаются, а “типичный” объем доступной памяти увеличивается, поэтому назвать, какой именно объем памяти является типичным, довольно затруднительно. Во время написания данной книги недорогие системы снабжались памятью объемом 128-256 Мбайт.

Понятие потоков вводится в главе 7.

Обычно для создания объектов типа X используются системные вызовы CreateX. Функция HeapCreate является исключением из этого правила.

Утверждение относительно согласованности отображенных представлений файлов, видимых разными процессами, неприменимо к сетевым файлам. Файлы должны быть локальными.

:/>  После изменения числа процессоров и максимума памяти windows перестала запускаться что делать

Главная |
В избранное |
Наш E-MAIL |
Добавить материал |
Нашёл ошибку |
Наверх