As operações de operação de bits da linguagem C incluem dois tipos, operações de operação lógica e operações de deslocamento lógico.
Operação lógica
A linguagem C fornece quatro operadores lógicos bit a bit, que são negação bit a bit AND, bit a bit OR e XOR a bit a bit. Durante a compilação, o compilador será convertido em instruções diferentes de acordo com a largura do operando.
Operação | Operador de linguagem C | Instruções de montagem |
---|---|---|
Negação bit a bit | ~ | notb 、 notw 、 notl |
Bit a bit e | & | andb 、 andw 、 andl |
Bit a bit ou | eu | cego, ORW, ENT |
Bitwise XOR | ^ | bebida 、 xorw 、 xorl |
Nota: O AND lógico (&&), OR lógico (||) e NOT lógico (!) Da linguagem C não possuem instruções de máquina correspondentes, mas várias instruções são combinadas para atingir essas funções e concluir operações lógicas em variáveis. .
Abaixo, usamos um programa de linguagem C simples test.c para entender o processo de operação lógica.
#include <stdio.h>
void main()
{
int a=5;
unsigned int b=3;
short c=5;
int d=0;
a = ~a;
b = ~b;
c = ~c;
d = a&b;
d = a^b;
d = a|b;
return;
}
Use o comando gcc para compilá-lo em um arquivo executável.
gcc -o0 -m32 -g test.c -o test
Use o comando objdump para desmontar e redirecioná-lo para o arquivo test.txt para facilitar a visualização.
objdump -S test>test.txt
As instruções de montagem correspondentes à função principal são as seguintes.
000004ed <main>:
#include <stdio.h>
void main()
{
4ed: 55 push %ebp
4ee: 89 e5 mov %esp,%ebp
4f0: 83 ec 10 sub $0x10,%esp
4f3: e8 48 00 00 00 call 540 <__x86.get_pc_thunk.ax>
4f8: 05 e4 1a 00 00 add $0x1ae4,%eax
int a=5;
4fd: c7 45 f4 05 00 00 00 movl $0x5,-0xc(%ebp)
unsigned int b=3;
504: c7 45 f8 03 00 00 00 movl $0x3,-0x8(%ebp)
short c=5;
50b: 66 c7 45 f2 05 00 movw $0x5,-0xe(%ebp)
int d=0;
511: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%ebp)
a = ~a;
518: f7 55 f4 notl -0xc(%ebp)
b = ~b;
51b: f7 55 f8 notl -0x8(%ebp)
c = ~c;
51e: 66 f7 55 f2 notw -0xe(%ebp)
d = a&b;
522: 8b 45 f4 mov -0xc(%ebp),%eax
525: 23 45 f8 and -0x8(%ebp),%eax
528: 89 45 fc mov %eax,-0x4(%ebp)
d = a^b;
52b: 8b 45 f4 mov -0xc(%ebp),%eax
52e: 33 45 f8 xor -0x8(%ebp),%eax
531: 89 45 fc mov %eax,-0x4(%ebp)
d = a|b;
534: 8b 45 f4 mov -0xc(%ebp),%eax
537: 0b 45 f8 or -0x8(%ebp),%eax
53a: 89 45 fc mov %eax,-0x4(%ebp)
return;
53d: 90 nop
}
53e: c9 leave
53f: c3 ret
Pode ser visto a partir do código acima que as três operações de negação de a, bec correspondem às seguintes instruções, respectivamente.
a = ~a;
518: f7 55 f4 notl -0xc(%ebp)
b = ~b;
51b: f7 55 f8 notl -0x8(%ebp)
c = ~c;
51e: 66 f7 55 f2 notw -0xe(%ebp)
As instruções de inversão da variável ae variável b são ambas notl, lidando com variáveis de 4 bytes. A instrução reversa da variável c executa notw e executa uma variável de 2 bytes. Isso significa que o compilador será convertido em instruções diferentes de acordo com a largura do operando.
A tabela a seguir fornece a correspondência entre os dados básicos e os tipos de linguagem C e os tipos de operando IA-32
Declaração de linguagem C | Sufixo do comprimento da instrução de montagem | Comprimento de armazenamento |
---|---|---|
(caracter não identifcado | b | 8 |
(não assinado) curto | W | 16 |
(não assinado) int | eu | 32. |
(não assinado) longo int | eu | 32. |
(não assinado) long long int | - | 2 $ \ vezes $ 32 |
Caracteres * | eu | 32. |
flutuador | s | 32. |
Duplo | eu | 64 |
longo duplo | t | 80/96 |
Ainda use o seguinte programa de linguagem C simples para entender a diferença entre operadores lógicos AND (&&), OR lógico (||), NOT lógico (!) E lógico bit a bit.
#include <stdio.h>
void main()
{
int a=5;
unsigned int b=3;
short c=5;
int d=0;
a = !a;
b = !b;
c = !c;
d = a&&b;
d = a||b;
return;
}
Compile-o com o comando gcc e, após a desmontagem do comando objdump, as instruções de montagem correspondentes à função principal são as seguintes.
000004ed <main>:
#include <stdio.h>
void main()
{
4ed: 55 push %ebp
4ee: 89 e5 mov %esp,%ebp
4f0: 83 ec 10 sub $0x10,%esp
4f3: e8 82 00 00 00 call 57a <__x86.get_pc_thunk.ax>
4f8: 05 e4 1a 00 00 add $0x1ae4,%eax
int a=5;
4fd: c7 45 f4 05 00 00 00 movl $0x5,-0xc(%ebp)
unsigned int b=3;
504: c7 45 f8 03 00 00 00 movl $0x3,-0x8(%ebp)
short c=5;
50b: 66 c7 45 f2 05 00 movw $0x5,-0xe(%ebp)
int d=0;
511: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%ebp)
a = !a;
518: 83 7d f4 00 cmpl $0x0,-0xc(%ebp)
51c: 0f 94 c0 sete %al
51f: 0f b6 c0 movzbl %al,%eax
522: 89 45 f4 mov %eax,-0xc(%ebp)
b = !b;
525: 83 7d f8 00 cmpl $0x0,-0x8(%ebp)
529: 0f 94 c0 sete %al
52c: 0f b6 c0 movzbl %al,%eax
52f: 89 45 f8 mov %eax,-0x8(%ebp)
c = !c;
532: 66 83 7d f2 00 cmpw $0x0,-0xe(%ebp)
537: 0f 94 c0 sete %al
53a: 0f b6 c0 movzbl %al,%eax
53d: 66 89 45 f2 mov %ax,-0xe(%ebp)
d = a&&b;
541: 83 7d f4 00 cmpl $0x0,-0xc(%ebp)
545: 74 0d je 554 <main+0x67>
547: 83 7d f8 00 cmpl $0x0,-0x8(%ebp)
54b: 74 07 je 554 <main+0x67>
54d: b8 01 00 00 00 mov $0x1,%eax
552: eb 05 jmp 559 <main+0x6c>
554: b8 00 00 00 00 mov $0x0,%eax
559: 89 45 fc mov %eax,-0x4(%ebp)
d = a||b;
55c: 83 7d f4 00 cmpl $0x0,-0xc(%ebp)
560: 75 06 jne 568 <main+0x7b>
562: 83 7d f8 00 cmpl $0x0,-0x8(%ebp)
566: 74 07 je 56f <main+0x82>
568: b8 01 00 00 00 mov $0x1,%eax
56d: eb 05 jmp 574 <main+0x87>
56f: b8 00 00 00 00 mov $0x0,%eax
574: 89 45 fc mov %eax,-0x4(%ebp)
return;
A explicação da operação da lógica de instruções da máquina não (!), Tomando a =! A como exemplo:
a = !a;
518: 83 7d f4 00 cmpl $0x0,-0xc(%ebp)
51c: 0f 94 c0 sete %al
51f: 0f b6 c0 movzbl %al,%eax
522: 89 45 f4 mov %eax,-0xc(%ebp)
Primeiro, compare a variável a com a constante 0, se for igual, defina o registro a1 como 1, caso contrário, defina-o como 0 e, em seguida, expanda o valor do registro a 0 para o registro eax e envie-o novamente a partir do registro eax Entre o endereço da variável a.
A explicação da operação da lógica de instruções da máquina e (&&) é explicada por d = a && b.
d = a&&b;
541: 83 7d f4 00 cmpl $0x0,-0xc(%ebp)
545: 74 0d je 554 <main+0x67>
547: 83 7d f8 00 cmpl $0x0,-0x8(%ebp)
54b: 74 07 je 554 <main+0x67>
54d: b8 01 00 00 00 mov $0x1,%eax
552: eb 05 jmp 559 <main+0x6c>
554: b8 00 00 00 00 mov $0x0,%eax
559: 89 45 fc mov %eax,-0x4(%ebp)
Primeiro, compare a variável a com 0. Se a variável a for igual a 0, pule para a posição 554, ou seja, execute a instrução mov $0x0,%eax
, ou seja, envie 0 para o registro eax e depois para a variável d. Se a variável a não for igual a 0, use a variável b para comparar com 0. Se b for igual a 0, pule para 554 para definir o resultado final como 0. Se a variável b não for igual a 0, envie 1 para No registro eax, defina o resultado final como 1.
Explicação da operação da lógica de instruções da máquina OR (||), explicada por d = a || b
d = a||b;
55c: 83 7d f4 00 cmpl $0x0,-0xc(%ebp)
560: 75 06 jne 568 <main+0x7b>
562: 83 7d f8 00 cmpl $0x0,-0x8(%ebp)
566: 74 07 je 56f <main+0x82>
568: b8 01 00 00 00 mov $0x1,%eax
56d: eb 05 jmp 574 <main+0x87>
56f: b8 00 00 00 00 mov $0x0,%eax
574: 89 45 fc mov %eax,-0x4(%ebp)
Primeiro, compare a variável a com 0. Se a variável a não for igual a 0, pule para a posição 558, ou seja, execute a instrução mov $0x1,%eax
, envie 1 para o registro eax, vá incondicionalmente para a posição 574 e defina o valor de eax Enviado para a variável d. Se a variável a é igual a 0, a variável b é comparada com 0, se b é igual a 0, então pule para a posição de 56f, para definir o resultado final como 0.
Operação de turno lógico
As operações de mudança de idioma C incluem mudança lógica para a esquerda, mudança aritmética para a esquerda, mudança lógica para a direita, mudança aritmética para a direita e assim por diante.
Operação | Operador de linguagem C | Instruções de montagem |
---|---|---|
Deslocamento lógico para a esquerda | << | shlb 、 shlw 、 shll |
Deslocamento aritmético para a esquerda | << | salb, salw, sall |
Deslocamento lógico para a direita | >> | encolher, encolher, encolher |
Deslocamento aritmético para a direita | >> | sarb 、 sarw 、 sarl |
Nota: Não há operação correspondente no idioma C para outras instruções de turno no IA-32. Se você deseja implementar uma instrução de turno cíclico, precisa escrever várias instruções para alcançá-lo.
Os operadores de linguagem C de mudança lógica e mudança aritmética são os mesmos, e o compilador escolherá instruções diferentes de acordo com os operandos diferentes. 无符号数采用逻辑移位指令,有符号数采用算术移位指令。逻辑和算术的区别在于友移时最高位补0还是补符号位。算术右移补入符号位,逻辑右移补入0
.
Ainda usamos uma instrução simples na linguagem C para introduzir a instrução de montagem da operação de mudança lógica.
#include <stdio.h>
void main()
{
int a = 0x80000000;
unsigned int b = 0x80000000;
short c = 0x8000;
unsigned short d = 0x8000;
a=a>>4;
b=b>>4;
a=c;
a=d;
b=c;
b=d;
return;
}
Compile-o com o comando gcc e, após a desmontagem do comando objdump, as instruções de montagem correspondentes à função principal são as seguintes
000004ed <main>:
#include <stdio.h>
void main()
{
4ed: 55 push %ebp
4ee: 89 e5 mov %esp,%ebp
4f0: 83 ec 10 sub $0x10,%esp
4f3: e8 46 00 00 00 call 53e <__x86.get_pc_thunk.ax>
4f8: 05 e4 1a 00 00 add $0x1ae4,%eax
int a = 0x80000000;
4fd: c7 45 f8 00 00 00 80 movl $0x80000000,-0x8(%ebp)
unsigned int b = 0x80000000;
504: c7 45 fc 00 00 00 80 movl $0x80000000,-0x4(%ebp)
short c = 0x8000;
50b: 66 c7 45 f4 00 80 movw $0x8000,-0xc(%ebp)
unsigned short d = 0x8000;
511: 66 c7 45 f6 00 80 movw $0x8000,-0xa(%ebp)
a=a>>4;
517: c1 7d f8 04 sarl $0x4,-0x8(%ebp)
b=b>>4;
51b: c1 6d fc 04 shrl $0x4,-0x4(%ebp)
a=c;
51f: 0f bf 45 f4 movswl -0xc(%ebp),%eax
523: 89 45 f8 mov %eax,-0x8(%ebp)
a=d;
526: 0f b7 45 f6 movzwl -0xa(%ebp),%eax
52a: 89 45 f8 mov %eax,-0x8(%ebp)
b=c;
52d: 0f bf 45 f4 movswl -0xc(%ebp),%eax
531: 89 45 fc mov %eax,-0x4(%ebp)
b=d;
534: 0f b7 45 f6 movzwl -0xa(%ebp),%eax
538: 89 45 fc mov %eax,-0x4(%ebp)
return;
A partir sarl $0x4,-0x8(%ebp)
desta instrução pode ser claramente visto quando se realiza uma operação de deslocamento para a direita de 4 bits, porque não há um número de símbolos, o deslocamento para a direita aritmética é realizada, o correspondente conjunto de instruções SARL. Ao executar o deslocamento à direita de b, porque b é um número não assinado, a instrução de deslocamento à direita lógica é executada, o que corresponde à instrução de montagem shrl.
a=c;
51f: 0f bf 45 f4 movswl -0xc(%ebp),%eax
523: 89 45 f8 mov %eax,-0x8(%ebp)
a=d;
526: 0f b7 45 f6 movzwl -0xa(%ebp),%eax
52a: 89 45 f8 mov %eax,-0x8(%ebp)
b=c;
52d: 0f bf 45 f4 movswl -0xc(%ebp),%eax
531: 89 45 fc mov %eax,-0x4(%ebp)
b=d;
534: 0f b7 45 f6 movzwl -0xa(%ebp),%eax
538: 89 45 fc mov %eax,-0x4(%ebp)
Pode-se observar nestas 8 instruções que, quando a = c é executado, a instrução de extensão de sinal é executada, quando z = d, a instrução de extensão zero é executada, quando b = c, a instrução de extensão de sinal é executada e quando b = d A instrução de extensão zero é executada. Então podemos ver isso 执行符号扩展还是零扩展是由等号右边的变量类型决定的,与等号左边的变量类型无关
.
O papel da aritmética de bits
- Consegue funções específicas : pegue bits específicos, reserve bits específicos
- Período curto e velocidade rápida : o deslocamento para a esquerda e o deslocamento para a direita podem ser usados para obter rápida multiplicação e divisão de números inteiros
- Outras funções podem ser realizadas : troca in situ
PS: troque os valores da variável ae variável b
Método comum
c = a; a = b; b = c;
Troca de manipulação de bits
a = a^b; b = b^a; a = a^b;
O princípio do método de manipulação de bits:
b = b^(a^b) = b^a^b = b^b^a = a
a = (a^b)^(b^(a^b)) = a^b^b^a^b = b
O conteúdo acima é as notas do estudo básico de sistemas de computador que compartilharei com você nesta operação de dados de pouco tempo. Também sou a primeira vez que comece. O que há de errado com isso? Eu acho que é bom elogiar um pouco o editor, você tem certeza da motivação do editor. Além disso, se você quiser aprender mais sobre o conhecimento e as habilidades profissionais do computador, apresente meu blog pessoal Beiluo.Além disso, sapatos infantis que precisam de vários materiais, você pode seguir minha conta pública do WeChat Beiluo , modelo PPT gratuito, vários materiais esperando por você Venha para liderar.