2011-11-13 11 views
7

Tengo una duda muy básica aquí. Tengo dos códigos C muy simples y sus códigos de montaje:En ensamblador, ¿por qué el uso de registros difiere entre suma y resta?

programa 1:

main() 

{ 

    int temp1, temp2, temp3; 
    char temp5, temp6, temp7, temp8, temp9; 
    temp1 = 5; 
    temp1 = 9 - temp1; 
} 

Asamblea:

0x080483b4 <+0>: push ebp  
    0x080483b5 <+1>: mov ebp,esp  
    0x080483b7 <+3>: sub esp,0x20  
    0x080483ba <+6>: mov DWORD PTR [ebp-0xc],0x5  
    0x080483c1 <+13>: mov eax,0x9  
    0x080483c6 <+18>: sub eax,DWORD PTR [ebp-0xc]  
    0x080483c9 <+21>: mov DWORD PTR [ebp-0xc],eax  
    0x080483cc <+24>: leave  
    0x080483cd <+25>: ret 

Programa 2:

main()  
{  
    int temp1, temp2, temp3; 
    char temp5, temp6, temp7, temp8, temp9; 
    temp1 = 5; 
    temp1 = 9 + temp1;  
} 

Asamblea:

0x080483b4 <+0>: push ebp  
    0x080483b5 <+1>: mov ebp,esp  
    0x080483b7 <+3>: sub esp,0x20  
    0x080483ba <+6>: mov DWORD PTR [ebp-0xc],0x5  
    0x080483c1 <+13>: add DWORD PTR [ebp-0xc],0x9  
    0x080483c5 <+17>: leave  
    0x080483c6 <+18>: ret 

Por qué en el caso de la resta, es necesario utilizar el registro eax y no en el caso de la suma. ¿No puede ser como:

0x080483c1 <+13>: sub DWORD PTR [ebp-0xc],0x9 

en lugar de -

0x080483c1 <+13>: mov eax,0x9 

0x080483c6 <+18>: sub eax,DWORD PTR [ebp-0xc] 
+0

no. En el código C, resta una variable de 9. En su conjunto debe restar un registro de 9, que es el del código de ensamblaje y no sub DWORD PTR [ebp-0xc], 0x9 . En el código de ensamblado, eax se resta con 5. En su premisa, resta 5 con 9. –

+0

¿compiló con las optimizaciones activadas? – ninjalj

+0

@ninjalj: Obviamente no lo hizo. Porque de lo contrario todo habría sido optimizado para un solo 'ret'. – celtschk

Respuesta

10

supongo porque además es conmutativa (A + B + A == B), mientras que la resta no es (A - B! = B - A). Debido a esto, la adición de 9 + temp1 es la misma que temp1 + 9, de ahí la secuencia de ensamblador más simple. 9 - temp1 implica la creación de una variable temporal.

+4

quiso decir conmutativa: medios asociativos * (A + B) + C == A + (B + C) * – Christoph

+4

De hecho, hice Cristoph, dos décadas desde mi última clase de matemáticas y dos cervezas entre esto y entonces. –

2

temp1 = 9 - temp1; es lo mismo que temp1 = - temp1 + 9;. Esto lleva a cabo operaciones: 2

  1. Negar temp1
  2. Haga la suma

eax se utiliza como la ubicación temporal para guardar el valor medio.

En el caso de adición, no hay "valor medio", la operación se puede hacer directamente.

+0

Esta respuesta no explica lo que se pregunta en la pregunta. Además, el código de ensamblaje no contiene una instrucción de negación. – Nayuki

2

La razón real de la conducta observada ha sido implicado por las otras respuestas, pero nunca se menciona de forma explícita:

conjuntos de instrucciones comunes incluyen operaciones para los siguientes cálculos:

%register := %register + $immediate [1] 
%register := %register - $immediate [2] 

Debido a conmutatividad, [1] también se puede utilizar para calcular

%register := $immediate + %register 

Sin embargo, un op dedicado para

%register := $immediate - %register 

es, en general, no está disponible, lo que significa que tiene que ser emulada, por ejemplo, por la secuencia de

%temp  := %register 
%register := $immediate 
%register := %register - %temp 
1

La razón es la falta de simetría en el conjunto de instrucciones x86, que no contiene una instrucciones para restar un registro de una constante.

Por ejemplo, el conjunto de instrucciones ARM contiene la instrucción RSB (Reverse SuBtract) exactamente para este propósito.

+0

En realidad, el conjunto de instrucciones ARM no es simétrico en este caso: carece de una instrucción 'reverse add' (por supuesto inútil), donde x86 en este caso es simétrica - carece de ambas instrucciones, el resta inverso útil y la adición inversa inútil . La razón más profunda para esto (y la necesidad de un sub inverso) es, por supuesto, la falta de simetría en la resta, no es conmutativa. – hirschhornsalz

+0

La simetría en este caso se encuentra entre las dos formas de hacer restas. – starblue

+1

Incidentalmente, los microcontroladores de la marca PIC tienen una instrucción de 'restar W de la constante', pero no 'restar constante del registro W', ya que la última instrucción podría simularse agregando 256-constante. – supercat

Cuestiones relacionadas