Почему ARM?

На самом деле этот пост должен был быть перед постом про «Наибольший общий делитель«. Так вот, почему меня заинтересовал именно ARM?

Несколько месяцев назад купил я на eBay супер-убийцу iPhone :) … SciPhone I9+++. Выглядит оно как iPhone, корпус пластиковый, сенсорный экран довольно тормозной. Это чудовище оказалось абсолютно неюзабельной вещью, из-за страшно неудобного оформления RTOS, которая там используется. RTOS Nucleus+. То ли у меня руки кривые, что я не могу им пользоваться, то ли сама система жутко недружелюбная. Китайская поДелка, одним словом.

Появилась некая слабая цель на горизонте — использовать телефон в качестве тестовой платформы для изучения программирования под ARM =). Цель довольно смутная, ибо я не представляю как и там и что (относительно конечно же).

В телефоне используется процессор MT6225 GSM/GPRS Baseband, максимальная частота 104Мгц. Основан он на базе 32-битных процессоров ARM7EJ-S RISC (ARMv5TEJ).
Расшифровав все эти непонятные буковки в названии процессора, узнал, что
T — Thumb mode
E — Enhanced DSP instructions
J — Jazelle DBX (исполнение Java-байткода самим процессором)

Скачав даташит по процессору, можно выудить кучу полезной информации, например, после инициализации процессор начинает исполнять код находящийся по адресу 0x48000000, работу с сим-картами, DMA-каналами, NAND-памятью, системе прерываний IRQ, FIQ и т.д..

Спаяв простенький COM-шнурок на микросхеме ST232BN вытащил из телефона дамп на 16Мб. Вот тут и случился затык. Вытаскивал дамп я программкой Spider Man. Отследил данные проходящие через COM-порт во время считывания / записи дампа, и нифига не понял :)

  • + Сначала ожидаем момент включения телефона и отсылаем ему код управления.
  • + Получаем ответ (как определить, что это ответ? неясно)
  • ! Начинается инициализация (отсылаются какие-то байты, получаются какие-то байты)
  • ! Начинаем грузить / проверять (?) загрузчик частями по 100 байт

что именно тут происходит, куда грузится загрузчик / где проверяется, в какой точке дампа начинается исполнение кода.. для меня темный лес.

Как именно записывать и считывать дамп в телефон самому я не разобрался. Исходников никаких нет. Для обработки дампов от, так называемых, «КИТов» существуют несколько программ, но все они платные, так же как «паучок».

P.S.
RISC-овый процессор может выполнить конструкцию:

a += (j << 2);

за один цикл :)

ADD Ra, Ra, Rj, LSL #2
Рубрика: Новости | Метки: , , , | Оставить комментарий

Вспоминаем Си. Ассоциативные массивы

Нужны ассоциативные массивы. Как об-Веб-ившемуся разработчику, уже привыкшему к ним, они просто необходимы. Ничего выдумывать не стал, а использовал уже написанный и отлаженный шаблон map из библиотеки C++ STL.

#include <windows.h> // magic include :)
#include <stdio.h>   // printf
#include <iostream>  // cin, cout
#include <string>    // будем использовать тип string
#include <map>       // будем использовать ассоциативный массив

using namespace std; // без этой штуки ничего работать не будет

int main() {
    typedef map<string,string> assoc;
    // объявляем наш массив
    //   индекс массива - string
    //   значение элементе - string
    assoc m;
    // объявляем итератор для пробега по массиву
    assoc::iterator pos;
    // это так.. тест
    string z;

    // присваиваем значения элементам массива
    m["pop"]   = "asda22sd";
    m["psdf"]  = "asdas33d";
    m["pod"]   = "asdfsdas55d";
    m["pjdkp"] = "asdas44d";
    z = m["pop"];

    // выводим все значения массива стандартными средствами C
    for (pos=m.begin(); pos != m.end(); pos++)
        printf("%s->%s\n", pos->first.c_str(), pos->second.c_str());

    // выводим все значения массива стандартными средствами C++
    for (pos=m.begin(); pos != m.end(); pos++)
        cout << pos->first << "->" << pos->second << endl;
}

Из минусов могу отметить, что бинарный код увеличивается килобайт эдак на 70. Во времена 8-ми битных машин это неслыханная роскошь.

Рубрика: Программирование | Метки: , | Оставить комментарий

Вспоминаем Си. Изменение ID элемента управления

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

  • выбор и подтверждение действия
  • исполнение действия

Казалось бы, можно просто использовать некие костыли, в виде статических или глобальных переменных, чтобы отслеживать на каком месте обработки мы находимся. Например:

...
// объявляем статическую переменную прямо в обработчике диалогового окна
// или делаем ее глобальной
static int stage;
...
case WM_COMMAND:
  switch (LOWORD(wparam)) {
    case IDC_BTN_PROCESS:
      // тыкнули на нашу кнопочку и попали сюда
      // определяем на какой стадии мы находимся
      switch (stage) {
        case 0:
          // тут что-то делаем на стадии 0
          ...
          // переходим на стадию 1
          stage = 1;
          break; // stage
        case 1:
          // тут что-то делаем на стадии 1
          break; // stage
      } // switch (stage)
      break; // IDC_BTN_PROCESS
  } // switch (LOWORD(wparam))
  break; // WM_COMMAND
...

Такое может прокатить при написании игрового движка, но мы сейчас пишем не его. Меня данная лестница switch / case / if не устроила, ибо задача у меня более простая. Да и интересовал, в общем-то момент смены / назначения ID. Таким образом у меня получился код такого вида:

...
case WM_COMMAND:
  switch (LOWORD(wparam)) {

    case IDC_BTN_STAGE0:
        // тут что-то делаем на стадии 0
        ...
        // переходим на стадию 1, изменяя ID нашей кнопочки
        SetWindowLong((HWND)lparam,GWL_ID,IDC_BTN_STAGE1);
        break; // IDC_BTN_STAGE0

    case IDC_BTN_STAGE1:
        // тут что-то делаем на стадии 1
        ...
        break; // IDC_BTN_STAGE1

  } // switch (LOWORD(wparam))
  break; // WM_COMMAND
...
Рубрика: Программирование | Метки: , | Оставить комментарий

Вспоминаем Си. RichEdit, прокрутка текста колесиком мыши

Понадобилась прокрутка текста внутри RichEdit элемента, даже в том случае, если оно не в фокусе. Долго думать не пришлось, все довольно тривиально:

LRESULT CALLBACK mainDlgProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
  switch (msg) {
  ..
  ..
  case WM_MOUSEWHEEL: {
    // catch MOUSE WHEEL message
    POINT  pos;
    GetCursorPos(&pos);
    if (WindowFromPoint(pos) == GetDlgItem(hwnd, IDC_RICHEDIT1)) {
      // process message, if cursor over our richedit control
      // get Delta
      int zDelta = GET_WHEEL_DELTA_WPARAM(wparam);

      if (zDelta > 0)
        // scroll up
        SendDlgItemMessage(hwnd, IDC_RICHEDIT1,WM_VSCROLL,SB_LINEUP,0L);
      else
        // scroll down
        SendDlgItemMessage(hwnd, IDC_RICHEDIT1,WM_VSCROLL,SB_LINEDOWN,0L);
      return 1L;
    }
    break;
  }
  ..
  ..

Грубо говоря, перехватываем сообщение WM_MOUSEWHEEL, каждый раз когда мы крутим колесико мыши, срабатывает вышеприведенный кусок кода. В нем мы определяем позицию курсора мыши в момент получения сообщения, сравниваем хэндл окна под ним с хэндлом нашего целевого RichEdit элемента. Если они совпадают, то начинаем смотреть в какую сторону это самое колесико крутилось. От себя — прокручиваем вверх, к себе — прокручиваем вниз.

Рубрика: Программирование | Метки: , , | Оставить комментарий

Вспоминаем Си. Richedit, Выравнивание текста

Задался вопросом как мне красиво выровнять текст по обоим границам, так сказать «сделать ему Justify» ?
Начиная с версии RichEdit 2.0, элемент управления может выравнивать текст от левого до правого края, и сделать это можно таким образом:

// hwnd - хэндл окна / диалога с элементом управления RichEdit
PARAFORMAT p; // структура для управления форматированием текста

// включаем расширенное форматирование и перенос строк
SendDlgItemMessage(hwnd, IDC_RICHEDIT1, EM_SETTYPOGRAPHYOPTIONS,
                   TO_ADVANCEDTYPOGRAPHY , TO_ADVANCEDTYPOGRAPHY );

memset(&p, 0, sizeof(p));   // заполняем всю структуру нулями
p.cbSize = sizeof(p);       // устанавливаем размер структуры
p.dwMask = PFM_ALIGNMENT;   // указываем, что мы хотим изменить выравнивание
p.wAlignment = PFA_JUSTIFY; // как именно мы хотим его изменить

// устанавливаем так нужное нам выравнивание текста между левой и правой краями
SendDlgItemMessage(hwnd, IDC_RICHEDIT1, EM_SETPARAFORMAT, 0L, (LPARAM)&p);
Рубрика: Программирование | Метки: , , | Оставить комментарий

Windows XP Pro, Отказ доступа

Еще один страдальческий опыт с системой Windows. Как-то раз решил я заглянуть в список работающий служб, тыкнул правой кнопочкой мыши на иконочку «Мой компьютер» и… получил окошко с надписью «Отказано в доступе». Некоторые пользователи, которым важен момент полного контроля за собственной железякой, отчаявшись могут в сердцах снести всю систему и потратить 2-4 часа на установку и настройку системы под собственные потребности. Но я по сути своей лентяй, и терять столько времени мне было жаль, так как ставить и заново настраивать все нужные мне программы откровенно скучно и рутинно. Поковырявшись внутри, погуглив на просторах интернета, нашелся способ вернуть все обратно. Для меня он сработал.
Итак,

сначала пробуем запустить консоль управления сервисами ручками из командной строки:

%SystemRoot%\system32\mmc.exe /s %SystemRoot%\system32\compmgmt.msc

если все в порядке то начинаем проверять переменные окружения:

  • кликаем правой кнопкой мыши на иконку «Мой Компьютер»
  • выбираем пункт меню «Свойства»
  • открываем вкладочку «Дополнительно»
  • тыкаем на кнопку «Переменные среды»

в части «Переменные среды пользователя…» проверяем две переменные, по умолчанию они такие:

TEMP %USERPROFILE%\Local Settings\Temp
TMP %USERPROFILE%\Local Settings\Temp

если их нет — создайте их
далее проверяем «Системные переменные», там должно присутствовать примерно это:

ComSpec %SystemRoot%\system32\cmd.exe
Path %SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem
PATHEXT .COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH
TEMP %SystemRoot%\TEMP
TMP %SystemRoot%\TEMP
windir %SystemRoot%

В моем случае, отсутствовала переменная «windir» (выделена красным цветом в таблице). Добавив ее в системные переменные окружения тут же все заработало, никаких отказов как не бывало.

Рубрика: Система | Метки: , , , , | Оставить комментарий

Вспоминаем Си. RichEdit Control

Когда-то давно, уже лет 7-10 назад, я довольно сносно писал на си. И даже что-то получалось. Сейчас же я настолько об-Web-ился, что не могу вспомнить даже самого элементарного. Конечно же будем использовать устаревшие методы чистый WinAPI. :) Итак:
Используемые инструменты:

Встретил проблему, рисуем в редакторе ресурсов / пишем сами в любом редакторе диалоговое окошко с элементом управления RichEdit.
Например:

#include <windows.h>
#include <commctrl.h>
#include <richedit.h>

#define IDD_MAIN2                               102
#define IDD_MAIN5                               105
#define IDC_RICHEDIT1                           1000
#define IDC_BTN_TEST                            1001
#define IDC_BTN_QUIT                            1002
//
// Dialog resources
//
LANGUAGE LANG_NEUTRAL, SUBLANG_SYS_DEFAULT
IDD_MAIN2 DIALOGEX 6, 5, 289, 260
STYLE DS_3DLOOK | DS_CENTER | DS_MODALFRAME | DS_SETFONT |
      WS_VISIBLE | WS_BORDER | WS_CAPTION | WS_DLGFRAME |
      WS_GROUP | WS_SYSMENU
EXSTYLE WS_EX_WINDOWEDGE
CAPTION "Test 2.0"
FONT 8, "Tahoma", 0, 0, 1
{
    PUSHBUTTON      "&Test", IDC_BTN_TEST, 235, 215, 46, 15
    PUSHBUTTON      "&Quit", IDC_BTN_QUIT, 236, 235, 46, 15
    CONTROL         "Rich Edit", IDC_RICHEDIT1, RICHEDIT_CLASS,
                    WS_TABSTOP | WS_BORDER | ES_AUTOHSCROLL | ES_READONLY,
                    6, 9, 276, 200
}

LANGUAGE LANG_NEUTRAL, SUBLANG_SYS_DEFAULT
IDD_MAIN5 DIALOGEX 6, 5, 289, 260
STYLE DS_3DLOOK | DS_CENTER | DS_MODALFRAME | DS_SETFONT |
      WS_VISIBLE | WS_BORDER | WS_CAPTION | WS_DLGFRAME |
      WS_GROUP | WS_SYSMENU
EXSTYLE WS_EX_WINDOWEDGE
CAPTION "Test 5.0"
FONT 8, "Tahoma", 0, 0, 1
{
    PUSHBUTTON      "&Test", IDC_BTN_TEST, 235, 215, 46, 15
    PUSHBUTTON      "&Quit", IDC_BTN_QUIT, 236, 235, 46, 15
    CONTROL         "Rich Edit", IDC_RICHEDIT1, "RICHEDIT50W",
                    WS_TABSTOP | WS_BORDER | ES_AUTOHSCROLL | ES_READONLY,
                    6, 9, 276, 200
}

пишем простенький сырец:

#include <windows.h>
#include <commctrl.h>
#include <richedit.h>

#define IDD_MAIN2                               102
#define IDD_MAIN5                               105
#define IDC_RICHEDIT1                           1000
#define IDC_BTN_TEST                            1001
#define IDC_BTN_QUIT                            1002

HINSTANCE hInst;

BOOL CALLBACK mainDlgProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
    switch (msg) {
        case WM_CLOSE:
            EndDialog(hwnd, 0);
            return 1L;
    }
    return 0L;
}


int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                     LPSTR lpCmdLine, int nCmdShow) {
    hInst = hInstance;
    return DialogBox(hInstance, MAKEINTRESOURCE(IDD_MAIN2),NULL,mainDlgProc);
}

компилим:

rc /r /fo test.res test.rc
cl -c /Fotest.obj test.cpp
link /release -out:test.exe kernel32.lib user32.lib test.obj test.res

И …. получаем фигу. При запуске программы, ничего не происходит. Она тихо вылетает с ошибкой.

Ковырялся я из-за отсутствия практики довольно долго, и в конце-концов нашел решение в виде:

...
//    return DialogBox(hInstance, MAKEINTRESOURCE(IDD_MAIN2),NULL,mainDlgProc);
    HMODULE hLib;

    if (hLib=LoadLibrary("RICHED32.DLL"))
        DialogBox(hInstance, MAKEINTRESOURCE(IDD_MAIN2),NULL,mainDlgProc);
    else
        MessageBox(NULL, "Error", "Sorry, can't start up!", MB_OK);

    if (hLib)
        FreeLibrary(hLib);
...

Компилим снова, и все прекрасно заработало. Однако «RICHED32.DLL» уже устарела, и вместо нее можно / нужно подгружать «MSFTEDIT.DLL» и вместо ресурса IDD_MAIN2 использовать IDD_MAIN5.

В итоге я получил такой исходник:

#include 
#include 
#include 

#define IDD_MAIN2                               102
#define IDD_MAIN5                               105
#define IDC_RICHEDIT1                           1000
#define IDC_BTN_TEST                            1001
#define IDC_BTN_QUIT                            1002

HINSTANCE hInst;

BOOL CALLBACK mainDlgProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
    switch (msg) {
        case WM_CLOSE:
            EndDialog(hwnd, 0);
            return 1L;
    }
    return 0L;
}


int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                     LPSTR lpCmdLine, int nCmdShow) {
    hInst = hInstance;
    HMODULE hLib;

    if (hLib=LoadLibrary("msftedit.dll"))
        DialogBox(hInstance, MAKEINTRESOURCE(IDD_MAIN5),NULL,mainDlgProc);
    else if (hLib=LoadLibrary("RICHED32.DLL"))
        DialogBox(hInstance, MAKEINTRESOURCE(IDD_MAIN2),NULL,mainDlgProc);
    else
        MessageBox(NULL, "Error", "Sorry, can't start up!", MB_OK);

    if (hLib)
        FreeLibrary(hLib);

    return 0;
}
Рубрика: Программирование | Метки: , , , | Оставить комментарий

Наибольший общий делитель

Читал тут документацию по ARM-процессорам, в качестве примера там был такой код:

обычный ассемблер, возьмем, к примеру x86

; eax, ebx - два целых числа, для которых ищем наибольший общий делитель

gcd:
    cmp eax,ebx ; сравниваем числа
    jz  stop    ; если они равны, то заканчиваем поиск, переходим на метку stop
    jl  less    ; если eax < ebx, переходим на метку less
    sub eax,ebx ; eax = eax - ebx
    jmp gcd     ; продолжаем поиск
less:
    sub ebx,eax ; ebx = ebx - eax
    jmp gcd     ; продолжаем поиск
stop:

а вот реализация этого же алгоритма на ARMе:

; r0, r1 - два целых числа, для которых ищем наибольший общий делитель

gcd:
   cmp   r0,r1    ; сравниваем r0 и r1
   subgt r0,r0,r1 ; если r0 > r1, то r0 = r0 - r1
   sublt r1,r1,r0 ; если r0 < r1, то r1 = r1 - r0
   bne   gcd      ; если r0 != r1, то продолжаем поиск

ARM вообще интересная штука и фичи довольно вкусные, вот часть из них:

  • Все инструкции 32-битные
  • Большинство инструкций исполняется за 1 цикл
  • Каждая инструкция может быть исполнена по условию

P.S.
вот вам код на PHP:

function gcd($a, $b) {
    while ($a != $b)
        if ($a>$b)
            $a -= $b;
        else
            $b -= $a;
    return $a;
}
Рубрика: Программирование | Метки: , , , , | Оставить комментарий

Вот такой сервис…

http://torrmag.com

конвертирует ваши и чужие торрент-файлы в магнитные ссылки..

пользуйтесь :)

Рубрика: Новости | Оставить комментарий

Ebay, PSP и штучки

Перед новым годом на аукционе ebay купил себе переходничок PhotoFast CR-5400 для PSP Slim. И вот сегодня оно пришло %). Переходничок предназначен для использования 1-2 microSD как 1 Memory Stick Pro Duo. Занятная штука, засунул две флешки по 16 гигов и получил одну, но 32 гига :). 32-гиговых соньковских флешек пока не видел, а это бюджетный вариант, и довольно неплохой. … Чуть не забыл, искал этот же переходник в инете (локально не нашел), так он стоит от 350р без пересылки, а то, что мне пришло обошлось в 117р с пересылкой из Гонконга :)

Рубрика: Оффлайн | Метки: , , , | Оставить комментарий

Nginx, Python и WSGI over FastCGI под Windows

Захотелось мне попробовать, что-нибудь такого «зеленого» и «длинного». Скачал Python. Но ведь вот незадача, как его подружить с nginx’ом не знаю. Скачал враппер для FastCGI под питон, попутно скачал и собрал отдельную библиотечку FastCGI, которая используется этим враппером. При запуске тестового скрипта выдается:

unknown listenType(0)

во всех how-to, что я наковырял в гугле, написано, что это нормально, что это хорошо и это есть гуд.

только вот куда это теперь приткнуть в nginx ?

Я в непонятках.

Нашел настройку IIS с питоном, но там видимо сервер сам запускает враппер и он уже самостоятельно начинает работать. С nginx такой фокус вроде не проходит, он по этой причине и не работает с чистым CGI.

Рубрика: Сервера | Метки: , , | Оставить комментарий

Полмесяца водки

Вот и закончились новогодние выходные дни. И слава Б-гу. 13 дней питаться салатами и выпивкой — ужас. Работать надо.. работать… Лентяйство растлевает и надоедает еще хуже, чем любое другое занятие.

Рубрика: Оффлайн | Оставить комментарий