Нет они по командам - одинаковые, разница в одной команде. Inc и Move, а всё остальное одинаково (за исключением создания и удаления).
Давайте посчитаем.
arr^ := b; - переводится в три команды процессора:
mov 0x42c000, %edx - записываем значение указателя arr с адреса 0x42c000 в регистр edx - чтение в регистр из памяти
mov 0x42c010, %al - записываем значение переменной b с адреса 0x42c010 в регистр al - чтение в регистр из памяти
mov %al, (%edx) - записываем значение регистра al (переменная b) в ячейку памяти по адресу в регистре edx (arr^) - запись из регистра в память
inc(arr); - смещаем указатель
addl 0x01, 0x42c000 - прямое прибавление 1 к значению в ячейке памяти 0x42c000, то есть, тут на самом деле происходит чтение и запись в одной команде.
Итого получаем три чтения из памяти в регистр и две записи из регистра в память
Теперь рассмотрим второй вариант.
arr[b] := b;mov 0x42c000, %eax - записываем значение указателя arr с адреса 0x42c000 в регистр eax - чтение в регистр из памяти
movzbl 0x42c010, %edx - записываем значение переменной b с адреса 0x42c010 в регистр edx c дополнением нулями до 64 бит - чтение в регистр из памяти
mov 0x42c010, %al - записываем значение переменной b с адреса 0x42c010 в регистр al - чтение в регистр из памяти
mov %сl, (%eax, %edx, 1) - записываем значение регистра cl (переменная b) в ячейку памяти по адресу в регистрaх eax+edx (arr[b]) - запись из регистра в память
Получаем три чтения из памяти в регистр и одну запись из регистра в память.
И, что интересно, в случае с массивом получается на одну операцию записи в память меньше. Все остальные команды обработки цикла в обоих случаях одинаковые.
Но в целом ассемблерный код как-то не особо порадовал. Оптимизация как таковая отсутствует. Регистровые переменные не используются, идёт постоянная загрузка данных, которые уже и так находятся в регистрах процессора. Зачем?