При написании кода на C я решил скомпилировать его в ассемблер и прочитать его - я просто время от времени делаю это - своего рода упражнение, чтобы заставить меня думать о том, что машина делает каждый раз Я пишу заявление на языке C.
В любом случае, я написал эти две строки на C
asm(";move old_string[i] to new_string[x]");
new_string[x] = old_string[i];
asm(";shift old_string[i+1] into new_string[x]");
new_string[x] |= old_string[i + 1] << 8;
(old_string
- это массив char
, а new_string
- это массив unsigned short
, поэтому, учитывая два символа, 42 и 43, это поместит 4342 в new_string[x]
)
Который дал следующий результат:
#move old_string[i] to new_string[x]
movl -20(%ebp), %esi #put address of first char of old_string in esi
movsbw (%edi,%esi),%dx #put first char into dx
movw %dx, (%ecx,%ebx,2) #put first char into new_string
#shift old_string[i+1] into new_string[x]
movsbl 1(%esi,%edi),%eax #put old_string[i+1] into eax
sall $8, %eax #shift it left by 8 bits
orl %edx, %eax #or edx into it
movw %ax, (%ecx,%ebx,2) #?
(Я комментирую это сам, чтобы я мог следить за тем, что происходит).
Я скомпилировал его с -O3, так что я также мог видеть, как компилятор оптимизирует определенные конструкции. В любом случае, я уверен, что это, вероятно, просто, но вот что я не понимаю:
первый раздел копирует char
из old_string[i]
, а затем перемещает его (от dx
) до (%ecx,%ebx)
. Затем следующий раздел копирует old_string[i+1]
, сдвигает его или упорядочивает, а затем помещает в то же место из ax
. Он помещает два 16-битных значения в одно и то же место? Разве это не сработает?
Кроме того, он смещает old_string[i+1]
к старшему мечу eax
, затем или edx
(new_string[x]
) в него ... затем помещает ax
в память! Не будет ли ax
просто содержать то, что уже было в new_string[x]
? таким образом, он сохраняет одну и ту же вещь в одном и том же месте в памяти дважды?
Есть что-то, что я пропускаю? Кроме того, я совершенно уверен, что остальная часть скомпилированной программы не имеет отношения к этому фрагменту ... Я прочитал до и после, чтобы найти, где хранится каждый массив и различные переменные, и каковы значения регистров было бы при достижении этого кода - я думаю, что это единственная часть сборки, которая имеет значение для этих строк C.
-
о, оказывается, комментарии сборки GNU начинаются с #.