怎样用C实现逻辑右移、和算术左移?

cnss 2001-10-01 09:51:17
如题
...全文
2695 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
老兄,我学习汇编语言时老师讲,我又翻了课本证实:
SAL 指令同 SHL,是同一条指令的两种助记符,他们执行的操作完全相同。
SAR 与 SHR 不同,SHR 连符号一起右移,左边高位补0,而 SAR 空位补的不是0,而是原来的符号位。

我用汇编语言编了一个小程序证实:

cseg segment byte
assume cs:cseg,ds:cseg,ss:cseg
org 100h
main proc near

shl ax,cl
sal ax,cl
shr ax,cl
sar ax,cl
ret

main endp
cseg ends
end main

编译结果:
t:\>debug 1.COM
-u
10F6:0100 D3E0 SHL AX,CL
10F6:0102 D3E0 SHL AX,CL
10F6:0104 D3E8 SHR AX,CL
10F6:0106 D3F8 SAR AX,CL
10F6:0108 C3 RET
10F6:0109 C54C8B LDS CX,[SI-75]
10F6:010C CAE307 RETF 07E3
10F6:010F B020 MOV AL,20
10F6:0111 50 PUSH AX
10F6:0112 51 PUSH CX
10F6:0113 E83400 CALL 014A
10F6:0116 833E6C4C00 CMP WORD PTR [4C6C],+00
10F6:011B 751B JNZ 0138
10F6:011D FF066C4C INC WORD PTR [4C6C]
-q

t:\>

void __fastcall TForm1::BitBtn3Click(TObject *Sender)
{
asm sal eax,cl
asm shl eax,cl
asm sar eax,cl
asm shr eax,cl
}

在 DEBUG 运行时:
0040193C 55 push ebp
0040193D 8BEC mov ebp,esp
0040193F 83C4F8 add esp,-0x08
00401942 8955F8 mov [ebp-0x08],edx
00401945 8945FC mov [ebp-0x04],eax
00401948 D3E0 shl eax,cl
0040194A D3E0 shl eax,cl
0040194C D3F8 sar eax,cl
0040194E D3E8 shr eax,cl
00401950 59 pop ecx
00401951 59 pop ecx
00401952 5D pop ebp
00401953 C3 ret

SAL 和 SHL 完全一样

看来C语言的算术移位和逻辑移位和汇编语言是一样的,根本没有必要用汇编语言去编

cnss 2001-10-04
  • 打赏
  • 举报
回复
http://www.csdn.net/expert/TopicView.asp?id=311853

到这里来
cnss 2001-10-04
  • 打赏
  • 举报
回复
to ybchen
谢谢了,确实能行
我用汇编做了逻辑右移和算术左移,现在把逻辑右改用C

我要的是真正的算术左移,看来只能是汇编了
  • 打赏
  • 举报
回复
cnss()老兄试过了没有?
  • 打赏
  • 举报
回复
逻辑移位:(unsigned)>> 和 (unsigned)<<
算术移位:(signed)>> 和 (signed)<<

int main(void)
{
int x = 0xabcd;
unsigned int y = 0xdcba;

x<<=2; //与 (signed int)x<<=2; 相同,因为变量本身是signed
(unsigned int)x<<=2;
x>>=2;
(unsigned int)x>>=2;

(signed int)y<<=2;
y<<=2;
(signed int)y>>=2;
y>>=2;

return x+y;
}

汇编结果:

_TEXT segment byte public 'CODE'
assume cs:_TEXT,ds:DGROUP
_main proc near
?debug C E80105312E63707012AD422B
;
; int main(void)
;
push bp
mov bp,sp
;
; {
; int x = 0xabcd;
;
mov dx,-21555
;
; unsigned int y = 0xdcba;
;
mov bx,-9030
;
;
; x<<=2;
;
shl dx,2
;
; (unsigned int)x<<=2;
;
shl dx,2
;
; x>>=2;
;
sar dx,2
;
; (unsigned int)x>>=2;
;
shr dx,2
;
;
; (signed)y<<=2;
;
shl bx,2
;
; y<<=2;
;
shl bx,2
;
; (signed)y>>=2;
;
sar bx,2
;
; y>>=2;
;
shr bx,2
;
;
; return x+y;
;
mov ax,dx
add ax,bx
;
; }
;
pop bp
ret
_main endp
?debug C E9
?debug C FA00000000
_TEXT ends

因为算术左移和逻辑左移的结果一样,所以都编译成逻辑的,而右移不同,编译结果也不同
cnss 2001-10-02
  • 打赏
  • 举报
回复
to ybchen(),我试了,确实是cui说的那样
; 15 : shl eax, cl
00022 d3 e0 shl eax, cl
; 16 : sal eax, cl
00024 d3 e0 shl eax, cl

00022,00024是编译以后的,都一样
  • 打赏
  • 举报
回复
楼上的回答完全错误!
C语言是分逻辑移位和算术移位的!当然有逻辑右移、和算术左移啦!
蚊子王 2001-10-01
  • 打赏
  • 举报
回复
>>我想知道怎样用C实现逻辑右移
还是内嵌ASM吧
蚊子王 2001-10-01
  • 打赏
  • 举报
回复
逻辑左移和算术左移事实上是一样的;逻辑右移C/C++中没有,JAVA里倒有一个(>>>)
vince_xu 2001-10-01
  • 打赏
  • 举报
回复
何谓逻辑左移?是不是循环左移?
cnss 2001-10-01
  • 打赏
  • 举报
回复
通过观看VC6生成的汇编代码:

GR[GRI] = GR[GRI] << ADR; //这是逻辑左移
GR[GRI] = GR[GRI] >> ADR; //这里却是算术右移
我觉得在一个编译系统里应该是一致的,但VC6好象不是样

所以,我想知道怎样用C实现逻辑右移和算术左移
gigix 2001-10-01
  • 打赏
  • 举报
回复

C语言的移位操作似乎不区分逻辑和算术的。JAVA有区分。
cnss 2001-10-01
  • 打赏
  • 举报
回复
哦,原来是这样啊

谢谢你
蚊子王 2001-10-01
  • 打赏
  • 举报
回复
to cnss():逻辑左移和算术左移事实上是一样(一个机器代码,两种表示),不信看看生成的机器代码?
cnss 2001-10-01
  • 打赏
  • 举报
回复
to cui:
逻辑左移是全都移,算术左移不移符号位

想了想,我还是内嵌ASM吧

谢谢大家!

69,369

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧