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).

:/>  Распаковка игровых ресурсов, часть 1

Также нужно сказать, что 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 является исключением из этого правила.

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

:/>  7 способов ускорить ваш компьютер на Windows 10 | Журнал Digital World

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

Оставьте комментарий

Adblock
detector