[تمرين] : عمل محاكاة للدالة rgb
#1
السلام عليكم و رحمة الله و بركاته

المطلوب : عمل دالة MakeRGB تعمل نفس عمل الدالة RGB
+ عمل محاكاة للدوال التالية GetRValue,GetGValue,GetBValue

PHP كود :
function MakeRGB(r, g, b: Byte): COLORREF;
function 
GetBValueX(RGB:Cardinal):Byte;
function 
GetGValueX(RGB:Cardinal):Byte;
function 
GetRValueX(RGB:Cardinal):Byte; 

الشروط :
- يمنع استخدام دوال جاهزة
- يمنع استخدام التعليمات التالية : XOR , OR,SHL,SHR,ROR,ROL
-يمكنك ان أحببت أن تستخدم الأسمبلي بشرط مراعاة الشرطين السابقين
المدة : أسبوع قابل للتمديد (على حسب الحلول)
[COLOR="Red"]انتهت مدة التمرين
[/COLOR]------------------------------------------------
عدد الأعضاء الذين استطاعوا حل التحدي اثنين فقط (كنت أتوقع الكثير ) :
[COLOR="red"]- B.M.AbdelAziZ
- ALmuhhnad[/COLOR]

حلول الأخ B.M.AbdelAziZ :
PHP كود :
{            By B.M.AbdelAziZ              }
function 
MakeRGB(r, g, b: Byte): COLORREF;
begin
  result
:=b*$10000+g*$100+r;
end;
function 
GetBValueX(RGB:Cardinal):Byte;
begin
  result
:= RGB div $10000;
end;
function 
GetGValueX(RGB:Cardinal):Byte;
begin
  result
:= RGB div $100;
end;
function 
GetRValueX(RGB:Cardinal):Byte;
begin
  result
:= RGB div 1;
end;
{-------------------------------------------------------------------------}
type
  TCoulor 
= record
    
case Integer of
      0
:(color: Dword);
      
1:(r,g,b,nop: byte);
  
end;
Var 
Coulor : TCoulor;
function 
MakeRGB2(r, g, b: Byte): COLORREF;
begin
  Coulor
.r:=r;
  
Coulor.g:=g;
  
Coulor.b:=b;
  
result:=Coulor.color;
end;
function 
GetBValueX2(RGB:Cardinal):Byte;
begin
  result
:=Coulor.b;
end;
function 
GetGValueX2(RGB:Cardinal):Byte;
begin
  result
:=Coulor.g;
end;
function 
GetRValueX2(RGB:Cardinal):Byte;
begin
  result
:=Coulor.r;
end; 
حلول الأخ ALmuhhnad :
PHP كود :
{            By ALmuhhnad               }
function 
MakeRGB(R,G,B : Byte):Cardinal ;
begin
  Result 
:= B * $10000;
  
asm
    MOV EAX
,0
    MOV EAX
,Result
    MOV AH
,G
    MOV AL
,R
    MOV Result
,EAX
  end
;
end;

function 
GetRValue_T(RGB : Cardinal):Byte ;
begin
  asm
    MOV EAX
,RGB
    MOV Result
,AL
  end
;
end;

function 
GetGValue_T(RGB : Cardinal):Byte ;
begin
  asm
    MOV EAX
,RGB
    MOV Result
,AH
  end
;
end;

function 
GetBValue_T(RGB : Cardinal):Byte ;
begin
  Result 
:= RGB div $10000;
end;  
{-------------------------------------------------------------------------}
function 
MakeRGB2(R,G,B : Byte):Cardinal ;
begin
  asm
    MOV EAX
,0
    MOV AL
,B
    MOV ECX
,$10000
    MUL EAX
,ECX
    MOV AL
,G
    MOV CX
,$100
    MUL AX
,CX
    MOV AL
,R
    MOV Result
,EAX
  end
;
end; 
function 
GetRValueX(RGB : Cardinal):Byte;
asm
  MOV BYTE PTR DS
:[Result],AL
end
;

function 
GetGValueX(RGB : Cardinal):Byte;
asm
  MOV BYTE PTR DS
:[Result],AH
end
;

function 
GetBValueX(RGB : Cardinal):Byte;
asm
  PUSH EAX
  MOV CL
,BYTE PTR DS:[ESP+2]
  
POP EAX
  MOV AL
,CL
end
;
function 
MakeRGB3(R,G,B : Byte):Cardinal;
asm
  MOV BYTE PTR DS
:[Result],AL
  MOV BYTE PTR DS
:[Result+1],DL
  MOV BYTE PTR DS
:[Result+2],CL
end
;  
function 
GetBValueX2(RGB : Cardinal):Byte;
asm
  SAR EAX
,$10
end
; 

حلول صاحب التحدي SMP3 :
PHP كود :
{    By SMP3       }
function 
GetRValueX(RGB:Cardinal):Byte;
var
  
RGBB:PByte;
begin
  RGBB
:= @RGB ;
  
Result:=RGBB^;
end;

function 
GetGValueX(RGB:Cardinal):Byte;
var
  
RGBB:PByte;
begin
  RGBB
:= @RGB ;
  
Inc(RGBB);
  
Result:=RGBB^;
end;

function 
GetBValueX(RGB:Cardinal):Byte;
var
  
RGBB:PByte;
begin
  RGBB
:= @RGB ;
  
Inc(RGBB,2);
  
Result:=RGBB^;
end;

function 
MakeRGB(R, G, B: Byte): COLORREF;
begin
 Result 
:= ((B * $10000) + (G * $100) - (B * $10000) and (G * $100))  ;
 
Result := Result + R - ( Result and R);
end;

{-------------------------------------------------------------------------------------}

type TRGB = record
     R
:Byte;
     
G:Byte;
     
B:Byte;
end;
PRGB= ^TRGB ;

function 
GetRValueX2(RGB:Cardinal):Byte;
var 
RGBStruc:PRGB;
begin
  RGBStruc
:=@RGB;
  
Result:=RGBStruc.R;
end;

function 
GetGValueX2(RGB:Cardinal):Byte;
var 
RGBStruc:PRGB;
begin
  RGBStruc
:=@RGB;
  
Result:=RGBStruc.G;
end;

function 
GetBValueX2(RGB:Cardinal):Byte;
var 
RGBStruc:PRGB;
begin
  RGBStruc
:=@RGB;
  
Result:=RGBStruc.B;
end;

function 
MakeRGB2(R,G,B:Byte):COLORREF;
var 
RGBStruc:TRGB;
    
RGB:PInteger;
    
P:PByte;
begin
  RGBStruc
.R:=R;
  
RGBStruc.G:=G;
  
RGBStruc.B:=B;
  
P:=@RGBStruc.B;
  
Inc(P);
  
P^:=$00;
  
RGB:=@RGBStruc.R;
  
Result:=RGB^;
end;

{-------------------------------------------------------------------------------------}
{
$IFNDEF PUREPASCAL}

function 
GetRValueX3(RGB:Cardinal):Byte;
asm
{$IFDEF CPUX64}
    
MOV AL,CL
{$ENDIF}
end;

function 
GetGValueX3(RGB:Cardinal):Byte;
asm
{$IFDEF CPUX64}
    
MOV AL,CH
{$ELSE  !CPUX64}
    
MOV AL,AH
{$ENDIF !CPUX64}
end;

function 
GetBValueX3(RGB:Cardinal):Byte;
asm
{$IFDEF  CPUX64}
    
BSWAP ECX
    MOV AL
,CH
{$ELSE  !CPUX64}
    
BSWAP EAX
    MOV AL
,AH
{$ENDIF !CPUX64}
end;

function 
MakeRGB3(R,G,B:Byte): COLORREF;
asm
{$IFDEF CPUX64}
    
MOV AL,CL
    MOV AH
,DL
    BSWAP EAX
    MOV AL
,R8B
    
XOR AL,AL //MOV AH,00
    
XCHG AL,AH
    BSWAP EAX
{$ELSE !CPUX64}
    
MOV AH,DL
    BSWAP EAX
    MOV AH
,CL
    
XOR AL,AL //MOV AL,00
    
BSWAP EAX
{$ENDIF !CPUX64}
end;

{-------------------------------------------------------------------------------------}

function 
GetRValueX4(RGB:Cardinal):Byte;{$IFDEF CPUX86}pascal;{$ENDIF}
asm
{$IFDEF CPUX86}
    
MOV  AL,[EBP+$8]
{
$ELSE !CPUX86}
    
PUSH RCX
    POP  RCX
    MOV  AL
,[RSP-$8]
{
$ENDIF !CPUX86}
end;
function 
GetGValueX4(RGB:Cardinal):Byte;{$IFDEF CPUX86}pascal;{$ENDIF}
asm
{$IFDEF CPUX86}
    
MOV  AL,[EBP+$9]
{
$ELSE !CPUX86}
    
PUSH RCX
    POP  RCX
    MOV  AL
,[RSP-$7]
{
$ENDIF !CPUX86}
end;
function 
GetBValueX4(RGB:Cardinal):Byte;{$IFDEF CPUX86}pascal;{$ENDIF}
asm
{$IFDEF CPUX86}
    
MOV  AL,[EBP+$A]
{
$ELSE !CPUX86}
    
PUSH RCX
    POP  RCX
    MOV  AL
,[RSP-$6]
{
$ENDIF !CPUX86}
end;

(*function 
MakeRGB4(R,G,B:Byte):COLORREF;
asm
{$IFDEF CPUX64}
    
MOV     [EBP+$8],CL
    MOV     
[EBP+$9],DL
    MOV     
[EBP+$A],R8B
    MOV     
[EBP+$B],$00
    MOV EAX
,[EBP+$8]
{
$ELSE !CPUX64}
    
MOV     [EBP-$4],AL
    MOV     
[EBP-$3],DL
    MOV     
[EBP-$2],CL
    MOV     
[EBP-$1],$00
    MOV EAX
,[EBP-$4]
{
$ENDIF !CPUX64}
end;*)

function 
MakeRGB4(R,G,B:Byte):COLORREF;
asm
{$IFDEF CPUX86}
    
MOV    BYTE [Result+$0],AL
    MOV    BYTE 
[Result+$1],CL
    MOV    BYTE 
[Result+$2],DL
{$ELSE}
    
MOV    BYTE [Result+$0],CL
    MOV    BYTE 
[Result+$1],DL
    MOV    BYTE 
[Result+$2],R8B
{$ENDIF}
    
MOV    BYTE [Result+$3],$00
end
;

{-------------------------------------------------------------------------------------}

function 
GetRValueX5(RGB:Cardinal):Byte;
asm
{$IFDEF CPUX86}
    
PUSH EAX
    POP  EAX
    MOV  AL
,BYTE PTR DS:[ESP-$4]
{
$ELSE  !CPUX86}
    
PUSH RCX
    POP  RCX
    MOV  AL
,[RSP-$8]
{
$ENDIF  !CPUX86}
end;
function 
GetGValueX5(RGB:Cardinal):Byte;
asm
{$IFDEF CPUX86}
    
PUSH EAX
    POP  EAX
    MOV  AL
,BYTE PTR DS:[ESP-$3]
{
$ELSE  !CPUX86}
    
PUSH RCX
    POP  RCX
    MOV  AL
,[RSP-$7]
{
$ENDIF  !CPUX86}
end;
function 
GetBValueX5(RGB:Cardinal):Byte;
asm
{$IFDEF CPUX86}
    
PUSH EAX
    POP EAX
    MOV AL
,BYTE PTR DS:[ESP-$2]
{
$ELSE  !CPUX86}
    
PUSH RCX
    POP  RCX
    MOV AL
,[RSP-$6]
{
$ENDIF  !CPUX86}
end;

{-------------------------------------------------------------------------------------}

function 
SwapX(X:Cardinal):Cardinal ;
asm
{$IFNDEF CPUX86}
   
MOV EAX,ECX
{$ENDIF}
   
BSWAP EAX
end
;

function 
GetRValueX6(RGB:Cardinal):Byte;
begin
Result
:=Byte(RGB);
end;

function 
GetGValueX6(RGB:Cardinal):Byte;
begin
Result
:=Byte(SwapX(WORD(RGB)*$10000));
end;

function 
GetBValueX6(RGB:Cardinal):Byte;
begin
Result
:=Byte(SwapX(RGB*$100));
//Result:=Byte(SwapX((RGB-WORD(RGB))*$100));
end;
{
$ENDIF !PUREPASCAL} 

هدية للأخ virtual :
PHP كود :
A Or B = (A+B) - (A And B) 
الرد
#2
وعليكم السلام ورحمة الله

حل سريع باستخدام IntToHex/StrToInt/Copy دون دعم لليونيكود

كود :
function MakeRGB(r, g, b: Byte): COLORREF; begin result:=StrToInt('$00'+IntToHex(b,2)+IntToHex(g,2)+IntToHex(r,2)); end; function GetBValueX(RGB:Cardinal):Byte; begin result:=StrToInt('$'+copy(IntToHex(RGB,8),3,2) ); end; function GetGValueX(RGB:Cardinal):Byte; begin result:=StrToInt('$'+copy(IntToHex(RGB,8),5,2) ); end; function GetRValueX(RGB:Cardinal):Byte; begin result:=StrToInt('$'+copy(IntToHex(RGB,8),7,2) ); end;
الرد
#3
b.m.abdelaziz كتب :وعليكم السلام ورحمة الله

حل سريع باستخدام inttohex/strtoint/copy دون دعم لليونيكود

[color="purple"]و عليكم السلام Smile
حل سليم و صحيح لكنك خالفت الشرط الأول !!![/color]
إقتباس :- يمنع استخدام دوال جاهزة
+ ليس هناك داعي لدعم اليونيكود في مثل هذه الحالات ..
الرد
#4
هل انت متأكد من عدم استخدام or ؟
الناتج للدالة MakeRGB على ما اعتقد سيكون
كود :
result := ( b shl 16) or (g shl 8 ) or r ;
بدون shl ستكون
كود :
result := (b * 65536) or (g * 256) or r;
الا اذا كان هناك emulation لل or بواسطة ال and ؟؟
الرد
#5
virtual كتب :الا اذا كان هناك emulation لل or بواسطة ال and ؟؟

نعم يمكن كتابتها بدون استخدام التعليمة or و بدون emulation Smile

ملاحظة : حول تعليمة shl

كود :
b:= a shl 1 shl 1 shl 1 shl 1 shl 1 shl 1 shl 1 shl 1; // a shl 8 . b:= a *2*2*2*2*2*2*2*2;// a shl 8 . b:= a * 256 ;// a shl 8 .
الرد
#6
على فكرة أخي virtual : يمكن عمل emulation للتعليمة or باستخدام ثلاث تعليمات مختلفة !!
-------------------------------
سأتركك تحاول معها Smile
الرد
#7
يبدو انها تعليمة واحدة فقط !
كود :
function MakeRGB(r,g,b : byte):COLORREF; begin result := (b * $ffff) + (g * $ff) + r; end;

a or b = a + b
a and b= a * b
الرد
#8
إقتباس :a or b = a + b
a and b= a * b
a or b = a + b => غير صحيح ..
ما رأيك ب :
كود :
80 or 82 = 82 <> 80 + 82
نفس الأمر للتعليمة and ..

حاول مرة أخرى ...
الرد
#9
إقتباس :حل سليم و صحيح لكنك خالفت الشرط الأول !!!
لم انتبه للشرط الاول بسبب السرعة...هذا حل أخر بوقت اقل من السابق!
كود :
function MakeRGB(r, g, b: Byte): COLORREF; begin result:=b*$10000+g*$100+r; end; function GetBValueX(RGB:Cardinal):Byte; begin result:= RGB div $10000; end; function GetGValueX(RGB:Cardinal):Byte; begin result:= RGB div $100; end; function GetRValueX(RGB:Cardinal):Byte; begin result:= RGB div 1; end;
الرد
#10
عفوا لم انتبه . جو العمل المتعب لم يترك لي مجال للتفكير
a or b = a + b صحيح لكن على مستوى البت الواحد 1 و 0
يبدو ان اجابة الاستاذ B.M.AbdelAziZ هي الصحيحة
الرد


التنقل السريع :


يقوم بقرائة الموضوع: بالاضافة الى ( 1 ) ضيف كريم