Array of pointers, VirtualAlloc and RtlMoveMemory. MASM, some kind of problem - pointers

Does anybody know how to fix the addElement function so it ends up as another element in the array. The idea is a dynamic array, where arrayPtr is a pointer to the first element, then new elements can be added dynamically and kept track of by increasing the arrayPtr value. So in-fact I think what it would end up being is an array of pointers to DbRecord structs in memory. Allocated by VirtualAlloc and copied by RtlMoveMemory. I am kinda of hung up on RtlMoveMemeory line. I feel like my line of thinking is correct.
.386
.model flat, stdcall
option casemap :none
include windows.inc
include user32.inc
include kernel32.inc
addElement PROTO: ptr DbRecord
.data?
DbRecord struct
Id dd ?
WordOne db 32 dup(?) ; db is define byte, set value of byte
WordTwo db 32 dup(?)
WordThree db 32 dup(?)
Year dd ?
DbRecord ends
arrayPtr dd ? ; pointer in memory to start of array
newElementPointer DbRecord <>
hStdOut dd ?
bytesWritten dd ?
.data
arrayCount dd 0
hello db 'Hello World!', 0
.code
main proc
LOCAL DbRecord01:DbRecord
mov [DbRecord01.Id], 1;
; any other way than one character at a time?
mov byte ptr [DbRecord01.WordOne], 'D'
mov byte ptr [DbRecord01.WordOne + 1], 'o'
mov byte ptr [DbRecord01.WordOne + 2], 'g'
mov byte ptr [DbRecord01.WordOne + 3], 0
mov byte ptr [DbRecord01.WordTwo], 'C'
mov byte ptr [DbRecord01.WordTwo + 1], 'a'
mov byte ptr [DbRecord01.WordTwo + 2], 't'
mov byte ptr [DbRecord01.WordTwo + 3], 0
mov byte ptr [DbRecord01.WordThree], 'E'
mov byte ptr [DbRecord01.WordThree + 1], 'y'
mov byte ptr [DbRecord01.WordThree + 2], 'e'
mov byte ptr [DbRecord01.WordThree + 3], 0
mov [DbRecord01.Year], 2022;
invoke GetStdHandle, STD_OUTPUT_HANDLE
mov [hStdOut], eax
invoke WriteConsole, hStdOut, offset hello, sizeof hello, offset bytesWritten, NULL
invoke addElement, addr DbRecord01
ret
main endp
addElement proc DbRecordPointer: ptr DbRecord
invoke VirtualAlloc, NULL, sizeof DbRecord, MEM_COMMIT, PAGE_READWRITE ; I beleive store a memory address in eax
invoke RtlMoveMemory, DbRecord ptr [eax], DbRecordPointer, sizeof DbRecord ; but how to use that memory address here?
ret
addElement endp
end main
EDIT/Update:
So yes part of the answer is just passing in eax.
I am here now
How do I get the value of eax ("memory location from VirtualAlloc",) where data was copied into arrayPtr (arrayPtr + count * sizeof DbRecord)
.386
.model flat, stdcall
option casemap :none
include windows.inc
include user32.inc
include kernel32.inc
addElement PROTO: ptr DbRecord
.data?
DbRecord struct
Id dd ?
WordOne db 32 dup(?) ; db is define byte, set value of byte
WordTwo db 32 dup(?)
WordThree db 32 dup(?)
Year dd ?
DbRecord ends
arrayPtr dword ? ; pointer in memory to start of array
; newElementPointer DbRecord <>
hStdOut dd ?
bytesWritten dd ?
.data
arrayCount dd 0
hello db 'Hello World!', 0
.code
main proc
LOCAL DbRecord01:DbRecord
mov [DbRecord01.Id], 1;
; any other way than one character at a time?
mov byte ptr [DbRecord01.WordOne], 'D'
mov byte ptr [DbRecord01.WordOne + 1], 'o'
mov byte ptr [DbRecord01.WordOne + 2], 'g'
mov byte ptr [DbRecord01.WordOne + 3], 0
mov byte ptr [DbRecord01.WordTwo], 'C'
mov byte ptr [DbRecord01.WordTwo + 1], 'a'
mov byte ptr [DbRecord01.WordTwo + 2], 't'
mov byte ptr [DbRecord01.WordTwo + 3], 0
mov byte ptr [DbRecord01.WordThree], 'E'
mov byte ptr [DbRecord01.WordThree + 1], 'y'
mov byte ptr [DbRecord01.WordThree + 2], 'e'
mov byte ptr [DbRecord01.WordThree + 3], 0
mov [DbRecord01.Year], 2022;
invoke GetStdHandle, STD_OUTPUT_HANDLE
mov [hStdOut], eax
invoke WriteConsole, hStdOut, offset hello, sizeof hello, offset bytesWritten, NULL
invoke addElement, addr DbRecord01
ret
main endp
addElement proc uses edx DbRecordPointer: ptr DbRecord
Local newElementPointer: Dword
invoke VirtualAlloc, NULL, sizeof DbRecord, MEM_COMMIT, PAGE_READWRITE ; I beleive store a memory address in eax
mov newElementPointer, eax
;invoke RtlMoveMemory, newElementPointer , DbRecordPointer, sizeof DbRecord ; but how to use that memory address here?
invoke RtlMoveMemory, eax , DbRecordPointer, sizeof DbRecord
mov edx, arrayCount
inc edx
mov arrayCount, edx
;mov dword ptr [arrayPtr+arrayCount], eax
ret
addElement endp
end main

Related

ThreadSanitizer (TSan) instrumentation using LLVM opt and TSan passes

My goal is to instrument my initial IR with proper calls to TSan runtime library functions using LLVM opt tool and TSan passes. In other words, I want to end up with similar TSan instrumentation as when using clang -fsanitize=thread -S but by directly using opt and TSan passes instead.
As far as I know, LLVM has two passes for TSan instrumentation: tsan-module (a module pass) and tsan (a function pass). Both passes are available by default in opt, i.e. are included in opt -print-passes report.
I choose tiny_race.c as my sample programe, where the main thread and the thread it spawns (Thread1) form a data race while accessing a global variable Global.
Here are the two steps I take to instrument the code my way:
Generating the initial LLVM IR for tiny_race.c:
clang -S -emit-llvm tiny_race.c -o tiny_race.ll
Using LLVM opt to instrument tiny_race.ll with the two TSan passes:
opt -passes='tsan-module,tsan' tiny_race.ll -S -o myInstrumented.ll
The above pass pipeline executes fine but the resulting myInstrumented.ll lacks some TSan instrumentations. More specifically:
Thread1 (child thread) is left completely un-instrumented.
main thread only has #__tsan_func_entry and #__tsan_func_exit instrumentations and its accesses to Global are not instrumented.
Could anyone please explain why my approach produces a partially-instrumented output? Any suggestion is greatly appreciated.
To better display the difference between the IR resulting from my approach and the expected one, bellow you can find definitions of main and Thread1 in each of them.
Here is myInstrumented.ll:
; Function Attrs: noinline nounwind optnone uwtable
define dso_local ptr #Thread1(ptr noundef %x) #0 {
entry:
%x.addr = alloca ptr, align 8
store ptr %x, ptr %x.addr, align 8
store i32 42, ptr #Global, align 4
%0 = load ptr, ptr %x.addr, align 8
ret ptr %0
}
; Function Attrs: noinline nounwind optnone uwtable
define dso_local i32 #main() #0 {
entry:
%0 = call ptr #llvm.returnaddress(i32 0)
call void #__tsan_func_entry(ptr %0) *****TSAN INSTRUMENTATION*****
%retval = alloca i32, align 4
%t = alloca i64, align 8
store i32 0, ptr %retval, align 4
%call = call i32 #pthread_create(ptr noundef %t, ptr noundef null, ptr noundef #Thread1, ptr noundef null) #4
store i32 43, ptr #Global, align 4
%1 = load i64, ptr %t, align 8
%call1 = call i32 #pthread_join(i64 noundef %1, ptr noundef null)
%2 = load i32, ptr #Global, align 4
call void #__tsan_func_exit() *****TSAN INSTRUMENTATION*****
ret i32 %2
}
And here is the resulting IR when using clang -fsanitize=thread -S -emit-llvm tiny_race.c which is my expected result:
; Function Attrs: noinline nounwind optnone sanitize_thread uwtable
define dso_local ptr #Thread1(ptr noundef %x) #0 {
entry:
%0 = call ptr #llvm.returnaddress(i32 0)
call void #__tsan_func_entry(ptr %0) *****TSAN INSTRUMENTATION*****
%x.addr = alloca ptr, align 8
store ptr %x, ptr %x.addr, align 8
call void #__tsan_write4(ptr #Global) *****TSAN INSTRUMENTATION*****
store i32 42, ptr #Global, align 4
%1 = load ptr, ptr %x.addr, align 8
call void #__tsan_func_exit() *****TSAN INSTRUMENTATION*****
ret ptr %1
}
; Function Attrs: noinline nounwind optnone sanitize_thread uwtable
define dso_local i32 #main() #0 {
entry:
%0 = call ptr #llvm.returnaddress(i32 0)
call void #__tsan_func_entry(ptr %0) *****TSAN INSTRUMENTATION*****
%retval = alloca i32, align 4
%t = alloca i64, align 8
store i32 0, ptr %retval, align 4
%call = call i32 #pthread_create(ptr noundef %t, ptr noundef null, ptr noundef #Thread1, ptr noundef null) #4
call void #__tsan_write4(ptr #Global) *****TSAN INSTRUMENTATION*****
store i32 43, ptr #Global, align 4
call void #__tsan_read8(ptr %t) *****TSAN INSTRUMENTATION*****
%1 = load i64, ptr %t, align 8
%call1 = call i32 #pthread_join(i64 noundef %1, ptr noundef null)
call void #__tsan_read4(ptr #Global) *****TSAN INSTRUMENTATION*****
%2 = load i32, ptr #Global, align 4
call void #__tsan_func_exit() *****TSAN INSTRUMENTATION*****
ret i32 %2
}

Returning a value pointed to by a pointer in x86 NASM

I'm trying to write a function in x86 NASM assembly that takes a pointer to a structure (structure contains pointer to a buffer) and 2 ints (x,y) which then computes the address of the byte containing (x,y) and returns the value in this address. (The buffer contains a bmp file) I have this function written in C and it works fine.
C function
int loadByte(imgInfo* pImg, int x, int y)
{
unsigned char *pPix = pImg->pImg + (((pImg->width + 31) >> 5) << 2) * y + (x >> 3);
return *pPix;
}
x86 function
load_byte:
push ebp ; prologue
mov ebp, esp
lea ecx, [ebp + 8]
mov ecx, [ecx] ; ecx = &imgInfo
mov eax, [ecx+0] ; eax = width
add eax, 31 ; eax = width + 31
sar eax, 5 ; eax = (width + 31) >> 5
sal eax, 2 ; eax = ((width + 31) >> 5) << 2
mul DWORD [ebp+16] ; eax * y
mov edx, [ebp+12] ; edx = x
sar edx, 3 ; edx = x>>3
add eax, edx ; eax = ((width + 31) >> 5) << 2 * y + (x >> 3)
mov edx, [ecx+8] ; edx = &pImg
add eax, edx
mov eax, [eax]
pop ebp ; epilogue
ret
I tried checking if the address computed in both functions is the same so I changed the return of C to return pPix and commented the line mov eax, [eax] in x86 and to my surprise both functions returned the same number but in the unchanged form (as in the code above) the x86 function always returns -1 for some reason. Is return *pPix not equivalent to mov eax, [eax]? What is wrong with my reasoning?
imgInfo struct
typedef struct
{
int width, height;
unsigned char* pImg; //buffer
int cX, cY;
int col;
} imgInfo;
load_byte C declaration
extern int load_byte(imgInfo* pInfo, int x, int y);

TSLtoRGB colorspace conversion

Someone knows the correct formula for RGBtoTSL ?
Wikipedia says that the conversion between RGB and TSL is made like this:
But....the reverse transformation presented on Wikipedia https://en.wikipedia.org/wiki/TSL_color_space is incorrect. The results presented by their reverted formula are not correct.
What is the proper formula to revert the transformation back ? I.e: transforming from TSL to RGB ?
Serg, here is some attempts we are making to try the revert operation :) Examples in Asm (RosAsm assembler).
; used variables
[Float_YIQ_Red_M1: R$ 0.29889531
Float_YIQ_Green_M2: R$ 0.58662247
Float_YIQ_Blue_M3: R$ 0.11448223]
[Float_minusOneThird: R$ (-1/3)] ; error in RosAsm. It canĀ“ see "-(1/3)"
[r1Factor: R$ 0]
[g1Factor: R$ 0]
[rFactor: R$ 0]
[gFactor: R$ 0]
[TmpFloat: R$ 0]
[Float_Var95: R$ (9/5)]
[Float_Var14: R$ (1/4)]
[Float_Var34: R$ (3/4)]
[Float_VarOne2Pi: R$ 0.159154943091895335768883763372514362034459645740456448747] ; 1/(2*pi)
[xFactor: R$ 0]
[kFactor: R$ 0]
[Float_Half: R$ 0.5]
[Float_Var59: R$ (5/9)]
[Float_Var53SquareRoot: R$ 0.745355992499929898803057889577092078480206119870508574756] ; sqrt(5)/3
[Float_OneThird: R$ (1/3)]
[FloatTSLVar1: R$ 0.184413]
[FloatTSLVar2: R$ 0.4721403]
[Float_TempRed: R$ 0]
[Float_TempGreen: R$ 0]
[Float_TempBlue: R$ 0]
[Float_Two_PI: R$ 6.283185307179586476925286766559005768394338798750211641948]
[Float_Five: R$ 5.0]
; -----------------------------------------------------------
Proc RGBtoTSL2a:
Arguments #PixelSrc, #Tint, #Saturation, #Light
Local #TempRed, #TempGreen, #TempBlue, #TempCmax, #TempCmin, #TempDelta_Max, #TempVar
Uses eax, ecx, esi, edi, edx, ebx
finit
; RGB from 0 to 255
; get RED
mov esi D#PixelSrc | movzx edi B$esi+ARGB.RedDis | lea ecx D#TempRed | mov D$ecx edi | mov eax edi
; get GREEN
mov esi D#PixelSrc | movzx edi B$esi+ARGB.GreenDis | lea ecx D#TempGreen | mov D$ecx edi | add eax edi
; get BLUE
mov esi D#PixelSrc | movzx edi B$esi+ARGB.BlueDis | lea ecx D#TempBlue | mov D$ecx edi | add eax edi
If eax = 0
fldz
mov esi D#Light | fst R$esi
mov esi D#Saturation | fst R$esi
mov esi D#Tint | fstp R$esi
ExitP
End_If
; Get Min and Max of RGB (just to get MIn/Max RGB to check for grey
lea ebx D#TempCmin | mov D$ebx 0
lea eax D#TempCmax | mov D$eax 0
call GetRGB_MinMax esi, ebx, eax
; Get Delta
; max = edx
; min = ecx
mov edx D#TempCmax | lea eax D#TempCmax | mov D$eax edx
mov ecx D#TempCmin | lea eax D#TempCmin | mov D$eax ecx
lea ebx D#TempDelta_Max | mov D$ebx 0; cmax-cmin
mov eax D#TempCmax | sub eax D#TempCMin | mov D$ebx eax
; 1st compute Light (Normalized)
mov esi D#Light
fild F#TempRed | fmul R$Float_YIQ_Red_M1
fild F#TempGreen | fmul R$Float_YIQ_Green_M2
faddp ST1 ST0
fild F#TempBlue | fmul R$Float_YIQ_Blue_M3
faddp ST1 ST0 | fmul R$FloatOne_255 | fstp R$esi
..If D#TempDelta_Max = 0; This is gray, no tint, no saturation
fldz
mov esi D#Saturation | fst R$esi
mov esi D#Tint | fstp R$esi
..Else
; 2nd compute Saturation
; get rfactor
lea edi D#TempVar
fild F#TempRed | fiadd F#TempGreen | fiadd F#TempBlue | fistp F$edi
fild F#TempRed | fidiv F$edi | fadd R$Float_minusOneThird | fstp R$rFactor
; get gfactor
fild F#TempGreen | fidiv F$edi | fadd R$Float_minusOneThird | fstp R$gFactor
mov esi D#Saturation
fld R$rFactor | fmul ST0 ST0
fld R$gFactor | fmul ST0 ST0
faddp ST1 ST0 | fmul R$Float_Var95
fsqrt | fstp R$esi
; 3rd compute Tint
mov esi D#Tint
fldz | fstp R$esi
fld R$rFactor | fdiv R$gFactor | fstp R$TmpFloat
Fpu_If R$gFactor > R$Float_Zero
fld R$TmpFloat | fld1 | fpatan | fmul R$Float_VarOne2Pi | fadd R$Float_Var14 | fstp R$esi ; result in radian
Fpu_Else_If R$gFactor < R$Float_Zero
fld R$TmpFloat | fld1 | fpatan | fmul R$Float_VarOne2Pi | fadd R$Float_Var34 | fstp R$esi ; result in radian
Fpu_End_If
..End_If
EndP
and the reverted function
Proc TSLtoRGB2a:
Arguments #Tint, #Saturation, #Light, #Red, #Green, #Blue
Local #TempRed, #TempGreen, #TempBlue
Uses eax, ecx, esi, edi, ebx
; check for light conditions
mov esi D#Light
Fpu_If R$esi = R$Float_Zero
mov edi D#Red | mov D$edi 0
mov edi D#Green | mov D$edi 0
mov edi D#Blue | mov D$edi 0
ExitP
Fpu_End_If
mov edi D#Saturation
mov esi D#Tint
;.Fpu_If_Or R$esi = R$Float_Zero, R$edi = R$Float_Zero ; Grey color found
; Not true. Tint = 0 not necessarily means grey. What means grey is
; saturation = 0
; see Serg examples:(44, 22, 0) and (0, 32, 64)
.Fpu_If R$edi = R$Float_Zero ; Grey color found. Seems to be only this case for finding grey.
mov ebx D#Light
fld R$ebx | fst R$Float_TempRed | fst R$Float_TempGreen | fstp R$Float_TempBlue
fld1 | fstp R$kFactor
.Fpu_Else
; compute -1 * cot(2*pi*Tint)
fld R$esi
fmul R$Float_Two_PI
fptan
fdivrp ST0 ST1
fmul R$Float_Minus_one
fstp R$xFactor
fld1 | fld R$xFactor | fmul ST0 ST0 | fadd R$Float_One | fdivp ST0 ST1 | fmul R$Float_Five
fsqrt | fmul R$Float_OneThird | fmul R$edi | fstp R$g1Factor
Fpu_If R$esi > R$Float_Half
fld R$g1Factor | fmul R$Float_Minus_One | fstp R$g1Factor
Fpu_End_If
fld R$g1Factor | fmul R$xFactor | fstp R$r1Factor
fld R$r1Factor | fadd R$Float_OneThird | fstp R$Float_TempRed
fld R$g1Factor | fadd R$Float_OneThird | fstp R$Float_TempGreen
fld1 | fsub R$Float_TempRed | fsub R$Float_TempGreen | fstp R$Float_TempBlue
; Compte KFactor
mov ebx D#Light
fld R$ebx
fld R$Float_TempRed | fmul R$FloatTSLVar1
fld R$Float_TempGreen | fmul R$FloatTSLVar2
faddp ST1 ST0 | fadd R$Float_YIQ_Blue_M3
fdivp ST1 ST0
fstp R$kFactor
.Fpu_End_If
mov edi D#Red | fld R$kFactor | fmul R$Float_TempRed | fmul R$Float255 | fistp F$edi
If D$edi <s 0
mov D$edi 0
Else_If D$edi > 255
mov D$edi 255
End_If
mov edi D#Green | fld R$kFactor | fmul R$Float_TempGreen | fmul R$Float255 | fistp F$edi
If D$edi <s 0
mov D$edi 0
Else_If D$edi > 255
mov D$edi 255
End_If
mov edi D#Blue | fld R$kFactor | fmul R$Float_TempBlue | fmul R$Float255 | fistp F$edi
If D$edi <s 0
mov D$edi 0
Else_If D$edi > 255 ; something still is incorrect.
; See what happens when:
; Tint = 0.85764542031
; Saturation: 0.0315199340953953
; Light = 0.8826082107058823529411764705882352941176
mov D$edi 255
End_If
EndP
Code was updated with a "negative zero" trick to handle T = 0 case
It is too big for a comment so I'll put it as an answer. I think that the formula at the wiki is correct and works OK in cases except 2 * G == R + B (i.e. except g' == 0 or in other words T == 0) in which case backward transformation is not unique mathematically. But in practice since we have both positive and negative zero on our hardware, we can use them do distinguish those bad cases.
Here is almost literal transformation of that formula into a JS:
function rgbFromTsl(T, S, L) {
if (arguments.length == 1) {
T = arguments[0][0];
S = arguments[0][1];
L = arguments[0][2];
}
if (L == 0)
return [0, 0, 0];
var r1, g1, x;
var r, g, b;
// For T == 0 reverse solution is not unique
// and we use a trick with "negative zero" to distinguish them
if (isNegativeZero(T)) {
g1 = 0;
r1 = -Math.sqrt(5.0) / 3.0 * S;
}
else if (T == 0) {
g1 = 0;
r1 = Math.sqrt(5.0) / 3.0 * S;
}
else {
x = -1.0 / Math.tan(2 * Math.PI * T);
g1 = Math.sqrt(5.0 / (1 + x * x)) / 3.0 * S;
if (T > 0.5)
g1 = -g1;
r1 = x * g1;
}
r = r1 + 1.0 / 3;
g = g1 + 1.0 / 3;
b = (1 - r - g);
var k = L / (0.185 * r + 0.473 * g + 0.114);
return [k * r, k * g, k * b];
}
and for the example you provided
try inputing this: Red = 128, Green = 22, Blue = 37 and once you find the TSL, try the reverse formula and you will see that it produced incorrect values (one of them negative, btw, which is impossible on rgb).
it seems to produce back the original R, G, B values with a quite good precision.
Here is a full runnable code that you can run just in place and play with some values. Let me know if you find some other bad cases except for 2*G = R+B aka T = 0
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>TSL/RGB</title>
<style>
div {
padding: 5px;
}
#container {
width: 550px;
}
input {
width: 150px;
}
#lc, #rc {
width: 220px;
border: dashed;
}
#lc {
float: left;
}
#rc {
float: right;
}
</style>
</head>
<body>
<div id="container">
<div id="lc">
<h1>RGB to TSL</h1>
<form name="RGBsrc">
<div id="RGBsrc">
<div>
<label for="Rsrc">R=</label> <input type="number" id="Rsrc" value="128">
</div>
<div>
<label for="Gsrc">G=</label> <input type="number" id="Gsrc" value="22">
</div>
<div>
<label for="Bsrc">B=</label> <input type="number" id="Bsrc" value="37">
</div>
</div>
<div id="TSLdst">
<div>
<label for="Tdst">T=</label> <input type="number" id="Tdst" disabled="disabled">
</div>
<div>
<label for="Sdst">S=</label> <input type="number" id="Sdst" disabled="disabled">
</div>
<div>
<label for="Ldst">L=</label> <input type="number" id="Ldst" disabled="disabled">
</div>
</div>
<div><button id="btnRgbToTsl">RGB to TSL</button></div>
<div><button id="btnCopyTsl">Copy result to TSL</button></div>
</form>
</div>
<div id="rc">
<h1>TSL to RGB</h1>
<form name="TSLsrc">
<div id="TSLsrc">
<div>
<label for="Tsrc">T=</label> <input type="number" id="Tsrc" value="0.5876633198969483">
</div>
<div>
<label for="Ssrc">S=</label> <input type="number" id="Ssrc" value="0.552900835318196">
</div>
<div>
<label for="Lsrc">L=</label> <input type="number" id="Lsrc" value="55.403999999999996">
</div>
</div>
<div id="RGBdst">
<div>
<label for="Rdst">R=</label> <input type="number" id="Rdst" disabled="disabled">
</div>
<div>
<label for="Gdst">G=</label> <input type="number" id="Gdst" disabled="disabled">
</div>
<div>
<label for="Bdst">B=</label> <input type="number" id="Bdst" disabled="disabled">
</div>
</div>
<div>
<label for="roundRgbDst">Round RGB</label> <input type="checkbox" id="roundRgbDst" checked="checked" style="width: 50px;" >
</div>
<button id="btnTslToRgb">TSL to RGB</button>
</form>
</div>
</div>
<script>
function isNegativeZero(v) {
return 1 / v === -Infinity;
}
function floatToStrSmart(v) {
if (isNegativeZero(v))
return "-0.0";
else
return "" + v;
}
function parseFloatSmart(s) {
if ((s === "-0") || (s === "-0.0"))
return -0.0;
else
return parseFloat(s)
}
function tslFromRgb(R, G, B) {
if (arguments.length == 1) {
R = arguments[0][0];
G = arguments[0][1];
B = arguments[0][2];
}
if ((R == 0) && (G == 0) && (B == 0)) {
return [0, 0, 0];
}
var L = 0.299 * R + 0.587 * G + 0.114 * B;
var r1 = R / (R + G + B) - 1.0 / 3;
var g1 = G / (R + G + B) - 1.0 / 3;
var S = Math.sqrt(9.0 / 5 * (r1 * r1 + g1 * g1));
var T;
if (g1 == 0) {
if (R < B)
T = -0.0;
else
T = 0.0
}
else {
T = Math.atan(r1 / g1) / Math.PI / 2 + 0.25;
if (g1 < 0)
T += 0.5;
}
return [T, S, L]
}
function rgbFromTsl(T, S, L) {
if (arguments.length == 1) {
T = arguments[0][0];
S = arguments[0][1];
L = arguments[0][2];
}
if (L == 0)
return [0, 0, 0];
var r1, g1, x;
var r, g, b;
// For T == 0 reverse solution is not unique
// and we use a trick with "negative zero" to distinguish them
if (isNegativeZero(T)) {
g1 = 0;
r1 = -Math.sqrt(5.0) / 3.0 * S;
}
else if (T == 0) {
g1 = 0;
r1 = Math.sqrt(5.0) / 3.0 * S;
}
else {
x = -1.0 / Math.tan(2 * Math.PI * T);
g1 = Math.sqrt(5.0 / (1 + x * x)) / 3.0 * S;
if (T > 0.5)
g1 = -g1;
r1 = x * g1;
}
r = r1 + 1.0 / 3;
g = g1 + 1.0 / 3;
b = (1 - r - g);
var k = L / (0.185 * r + 0.473 * g + 0.114);
return [k * r, k * g, k * b];
}
document.getElementById('btnRgbToTsl').addEventListener('click', function (e) {
e.preventDefault();
var r = parseInt(document.getElementById('Rsrc').value);
var g = parseInt(document.getElementById('Gsrc').value);
var b = parseInt(document.getElementById('Bsrc').value);
document.getElementById('Rsrc').value = r;
document.getElementById('Gsrc').value = g;
document.getElementById('Bsrc').value = b;
var tsl = tslFromRgb(r, g, b);
var t = tsl[0];
var s = tsl[1];
var l = tsl[2];
document.getElementById('Tdst').value = floatToStrSmart(t);
document.getElementById('Sdst').value = s;
document.getElementById('Ldst').value = l;
});
document.getElementById('btnCopyTsl').addEventListener('click', function (e) {
e.preventDefault();
document.getElementById('Tsrc').value = document.getElementById('Tdst').value;
document.getElementById('Ssrc').value = document.getElementById('Sdst').value;
document.getElementById('Lsrc').value = document.getElementById('Ldst').value;
});
document.getElementById('btnTslToRgb').addEventListener('click', function (e) {
e.preventDefault();
var t = parseFloatSmart(document.getElementById('Tsrc').value);
var s = parseFloat(document.getElementById('Ssrc').value);
var l = parseFloat(document.getElementById('Lsrc').value);
document.getElementById('Tsrc').value = floatToStrSmart(t);
document.getElementById('Ssrc').value = s;
document.getElementById('Lsrc').value = l;
var rgb = rgbFromTsl(t, s, l);
var r = rgb[0];
var g = rgb[1];
var b = rgb[2];
if (document.getElementById('roundRgbDst').checked) {
document.getElementById('Rdst').value = (r + .1) | 0; //round to int
document.getElementById('Gdst').value = (g + .1) | 0; //round to int;
document.getElementById('Bdst').value = (b + .1) | 0; //round to int;;
}
else {
document.getElementById('Rdst').value = r;
document.getElementById('Gdst').value = g;
document.getElementById('Bdst').value = b;
}
});
</script>
</body>
</html>

What do I need to do before i switch / change a pointer variable pointed-to?

I do not want to mess up my RAM or make problem / bug that related to memory.
So.. what do I need to do before i switch / change a variable pointer pointed-to?
Or.. what i've doing is just fine?
Here is my source code:
#include <stdio.h>
int main(int argc, char *argv[])
{
int x = 10;
int y = 87;
int arr[5] = {1,2,3,4,5};
int *ptr;
ptr = &x;
printf("Now ptr pointed to x --> *ptr = %d ~ ptr address: %p \n", *ptr, ptr);
ptr = &y;
printf("Now ptr pointed to y --> *ptr = %d ~ ptr address: %p \n", *ptr, ptr);
ptr = arr;
printf("1st 2 byte: %d \n", *ptr);
*ptr++;
printf("2nd next 2 byte: %d \n", *ptr);
*ptr++;
printf("3rd next 2 byte: %d \n", *ptr);
*ptr++;
printf("4th next 2 byte: %d \n", *ptr);
// Now i want to switch to x again :D
ptr = &x;
printf("Now ptr pointed to x AGAIN --> *ptr = %d ~ ptr address: %p \n", *ptr, ptr);
return 0;
}
Please enlightenment.
Thank You
There doesn't seem to be a problem with what you have. The pointer is simply changing where it points to, but those background variables are not being changed at all. The variables x, y and your array will be alive for as long as the main function is running, as they are within the scope of main. If you want them to be alive for even less time, you could restrict them to other functions that are called from main.
void xVariable()
{
int x = 7;
}
int main()
{
int y = 8;
xVariable();
for(int i = 0; i < 9; i++)
{
int z = 9;
}
return 0;
}
In this example, y will be alive the entire run of the program. x will only be alive while the function xVariable is running. i and z are only alive for the duration of the loop. This is all a basic example of how variable scope works, but I would recommend looking it further if memory is going to be important.

for loop acts abnormally in Arduino

Consider the following loop in C:
int i;
for (i = 1; i > 0; i++);
After i reaches INT_MAX, it will turn INT_MIN at increment. Then i > 0 evaluates
false, and the for loop will terminate.
However, the same for loop will not terminate in Arduino, since i > 0 compares false
even if i is -32768.
Why is that?
PS. I'm using a Mega 2560 with Arduino version 1.0.5.
PPS. int is indeed 16 bit on Mega 2560
PPPS. The complete sketch below:
void setup () {
int i;
Serial.begin(9600);
for (i = 1; i > 0; i++);
}
void loop () {
Serial.println(100);
}
And I won't see any thing in the Serial Monitor
Disassembling the setup function gives:
0000014a <setup>:
14a: 80 e3 ldi r24, 0x30 ; 48
14c: 94 e0 ldi r25, 0x04 ; 4
14e: 40 e8 ldi r20, 0x80 ; 128
150: 55 e2 ldi r21, 0x25 ; 37
152: 60 e0 ldi r22, 0x00 ; 0
154: 70 e0 ldi r23, 0x00 ; 0
156: 42 d2 rcall .+1156 ; 0x5dc <_ZN14HardwareSerial5beginEm>
158: ff cf rjmp .-2 ; 0x158 <setup+0xe>
so now it's clear: avr-gcc thinks the i > 0 in for(i = 1; i > 0; i++) will never evaluates false and optimised the exit condition away.
Most likely, 'int' is also 32-bit on Arduino. It takes time to complete 2^31 iterations. You may change 'int' to 'short' and it should terminate as expected.
when int is defined, by default, its size is assumed to be of 16 bit by compiler.
But when you increment it beyond 32767 i.e.
int i=32767;
i++;
The size of 'i' is automatically increased to 32 bit. This is because the size is not specified in the declaration.
This causes your program not to stop at 32767.
Hence if you want to stop the for loop at 32767,
you have to specifically declare it as
short int i;
If you want to verify this, you can try following
short int x;
for(x=1; x>0; x++)
{
mySerial.println(x);
}
AND
int x;
for(x=1; x>0; x++)
{
mySerial.println(x);
}

Resources