I have some masm syntax code on Windows in this way:
stru_40DBA0 dd 0FFFFFFFEh ; GSCookieOffset ; SEH scope table for function 402B22
dd 0 ; GSCookieXOROffset
dd 0FFFFFFC0h ; EHCookieOffset
dd 0 ; EHCookieXOROffset
dd 0FFFFFFFEh ; ScopeRecord.EnclosingLevel
dd 0 ; ScopeRecord.FilterFunc
offset $LN19 ; ScopeRecord.HandlerFunc
.....
Foo proc near
....
$LN19:
....
masm will generate errors at the offset $LN19 line, and I tried to modify it in this way:
PTR PROTO $LN29
Could anyone give me some help on how to declare this? Thank you!
There are really two things you need to do:
Ensure the label is public so it can be seen where you're using its offset.
Ensure the label has been declared where you're using its offset.
The easy way to do the latter is define your structure after the label itself has been defined.
To make the label public, you can either declare it public explicitly, like:
public $LN19
...or where you've defined the label, you can use two colons instead of one:
$LN19::
Related
While I debug with GDB I can print string:
x/s $r0
The output is
IDog123456
I want to change the value so when I print x/s $r0 I will see
ICat45555
I have tried to :
set $r0+1 ={int} 0x43617434 #Cat4
set $r0+5 ={int} 0x35353535 #5555
But it doesn't work , How can I do that without malloc ? only with hex string please?
Generally, the gdb expression parser operates similar to the current language, so, in the above, when you write:
set $r0+1 ={int} 0x43617434 #Cat4
The left hand side is an integer constant, which can't be assigned to.
Instead, you should write this as you would in C:
set *($r0+1) = (int) 0x43617434
Which should do the job.
Sometime, you might end up needing to case the pointer of the LHS too, like this:
set *((int *) ($r0+1)) = (int) 0x43617434
But I suspect in your case you'll be OK.
I am trying to analyze a byte code consisting of a store instruction with inttoptr. I am having trouble to detect whether a store instruction has the inttoptr value as the value operand (3rd instruction in the following code in entry BB). My opcode looks like the following:
define dso_local i32 #test(i32* %p) #0 {
entry:
%p.addr = alloca i32*, align 8
store i32* %p, i32** %p.addr, align 8
store i32* inttoptr (i64 1000 to i32*), i32** %p.addr, align 8
%0 = load i32*, i32** %p.addr, align 8
%1 = load i32, i32* %0, align 4
ret i32 %1
}
I am trying to analyze the store instruction and trying to find whether inttoptr is in a store instruction by using classof method and with dyn_cast like the following code:
StoreInst *store = dyn_cast<StoreInst>(I);
Value *vv = store->getValueOperand();
Value *vp = store->getPointerOperand();
if(IntToPtrInst::classof(vv)){
outs() << "Inttoptr found\n";
}
if(Instruction *inp = dyn_cast<IntToPtrInst>(vv)){
outs() << "Inttoptr found\n";
}
It seems I am not being able to detect inttoptr with any of the methods. I know the byte code is not creating a separate instruction for the inttoptr but it is merging with the store instruction. It would be really nice if anyone points me what I am missing and how I can detect the inttoptr in a store instruction.
The cast you're interested in is not an instruction, but rather a constant cast from the constant integer 1000 to a pointer. You can detect it using a test like isa<ConstantExpr>(foo->getPointerOperand()) && cast<ConstantExpr>(foo->getPointerOperand())->getOpcode() == ConstantExpr::IntToPtrCast, but I typed that from memory and I'm sure there are typos.
When you read IR, instructions are always on their own line, while constants are inline as arguments or initialisers, even the quite complex constants produced using ConstantExpr.
I have a sas program that merges two datasets containing information on a given city. The city name is part of the title of every dataset, e.g. for Atlanta:
data work.AtlantaComplete;
merge dir.Atlanta1 dir.Atlanta2;
by mergevar;
run;
I would like to run the merge on a long list of cities without having to make a separate .sas file for each one. With limited knowledge of SAS I tried the following:
%let city1 = Boston;
...
%let cityN = Miami;
%DO for i = 1 to N;
data work.city&i;
set dir.city&i.1 dir.city&i.2;
by mergevar;
run;
This produced several errors, the main one being that %DO statements must be inside a data step. This won't work for my task because the loop has to be defined before the first data step.
A solution that can be implemented within the sas program would be optimal, but I am also open to something like a Unix Bash shell script that provides each city one at a time as a system input to the sas program (similar to sys.argv in Python).
Thanks for your help
You have several small mistakes in your program.
Executing a %do loop is normally done inside a macro. Also you dont use keyword "for" and need a % in front of the to.
so try this:
%let city1 = Boston;
...
%let cityN = Miami;
%let N = 42; *or whatever your N is...;
%macro mergecities(citynumber);
%DO i = 1 %to &citynumber;
data work.&&city&i;
set dir.&&city&i dir.&&city&i;
by mergevar;
run;
%end;
%mend;
%mergecities(&N);
Instead of using the macrovariable citynumber you can directly use &N inside the do loop, but used with a parameter the macro is more flexible...
If you have numbered macro variables, you use &&varname&i to resolve them. Also, by having your cities in a dataset, you can create the macro variables off the back of it, rather than hard-coding them all (plus the count).
data cities ;
input City $20. ;
/* Create numbered macro variables based on _n_ */
call symputx(cats('CITY',_n_),City) ;
call symputx('N',_n_) ;
datalines ;
Atlanta
Boston
Chicago
Houston
Texas
;
run ;
%MACRO LOOP ;
%DO I = 1 %TO &N ;
data &&CITY&I..Complete ;
merge dir.&&CITY&I..1
dir.&&CITY&I..2 ;
by mergevar ;
run ;
%END ;
%MEND ;
%LOOP ;
I want to use a macro do loop inside proc iml like so:
%Let Tab1=FirstTable;
%Let Tab2=SecondTable;
%Let Tab3=ThirdTable;
*&Tab1-3 have been initialised as sas datasets;
proc iml;
* This works;
use &Tab1;
read all into Mat3;
print Mat3;
* This doesn't work;
%Macro Define_mx;
%do i=1 %to 2;
use &Tab&i;
read all into Mat&i ;
%end;
%Mend Define_mx;
%Define_mx;
*The two matrixes have not been initialised;
print Mat1;
print Mat2;
quit;
In reality I will have to initialise like 50 matrixes so a do-loop is necessary.
I can't figure out why the loop can't see &Tab&i as a macro variable.
I also tried a workaround with a normal (non-macro) do-loop using substr to concatenate the variable names but it didn't work either. What am I missing here ?
Ok, so the macro should be:
%Macro Define_mx;
%do i=1 %to 2;
use &&Tab&i;
read all into Mat&i ;
%end;
%Mend Define_mx;
%Define_mx;
The second amperstand on Tab is necessary as without it the macro processor would try to interpret &Tab as a macro variable (which does not exist). Thus, when trying to concatenate multiple macro variables to create a new one, use &&.
If you have SAS/IML 12.1 (released with 9.3m2), there is an even simpler way.
The USE statement supports dereferencing data set names, like this:
ds = "MyData";
use (ds);
Furthermore, as I show in my article on using the VALSET function, the SAS/IML language supports the VALSET function, which can dynamically create matrices named Mat1, Mat2, and so on.
You can combine these features to eliminate the macros entirely:
data a b c; /* create sample data sets */
x=1;y=2; output;
x=2;y=3; output;
run;
proc iml;
dsnames = {a b c}; /* names of data sets */
do i = 1 to ncol(dsnames);
use (dsnames[i]); /* open each data set */
read all into X;
close (dsname);
MatName = "Mat"+strip(char(i)); /* create Mat1, Mat2,... */
call valset(MatName, X); /* assign values from data set */
end;
show names;
I have a little problem. I want to have an Edit control in which is a text (something like this: "ABC#") . This string must be non editable so that the user shouldn't be able to delete it. The user should be able to type a text after the sign '#' only. I know how to make text readonly in editbox. I use EM_SETREADONLY message
//global variables
#define ID_TEXTBOX 1
static HWND hwndTextBox;
//in WndProc function
case WM_CREATE:
{
hwndTextBox = CreateWindow(TEXT("EDIT"),TEXT("abc#"),WS_VISIBLE | WS_CHILD | WS_BORDER ,70,100, 200,25,hWnd,(HMENU)ID_TEXTBOX,NULL,NULL);
if(!hwndTextBox )
{
MessageBox(hWnd,"Failed","Failed",MB_OK);
return FALSE;
}
SendMessage(hwndTextBox,EM_SETREADONLY,TRUE ,NULL);
break;
}
but the code makes whole text readonly and of course does not solve my problem.
Use a RichEdit control instead of an Edit control. Use the EM_SETCHARFORMAT message to mark individual characters, or ranges of characters, as "protected". Use the EM_SETEVENTMASK message to register for EN_PROTECTED notifications from the RichEdit. That way, if a user tries to modify one or more protected characters for any reason, the RichEdit will ask for your permission before allowing the modification.
This is probably not what you're looking for, but it may mimic the required functionality with just a bit of code overhead.
You can subclass the edit control and then through WM_CHAR message capture any of the user input that may modify the edit box contents. Once the message is received by your procedure, you detect the current selection (that is the caret position) in the edit box and if it's anywhere inside the first four characters you simply don't allow the change. This is a bit crude method, but it should work.
Example in assembly, sorry I'm not proficient enough in C and C is such a drag :D
invoke SetWindowLong,hEditBox,GWL_WNDPROC,offset EditProc
mov DefEditProc,eax
...
EditProc proc hWnd:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD
cmp uMsg,WM_CHAR
je #WM_CHAR
cmp uMsg,WM_KEYUP
je #WM_KEYUP
#DEFAULT:
invoke CallWindowProc,DefEditProc,hWnd,uMsg,wParam,lParam
ret
#EXIT:
xor eax,eax
ret
;=============
#WM_KEYUP:
mov eax,wParam ; you will need this if you want to process the delete key
cmp ax,VK_DELETE
je #VK_DELETE
jmp #DEFAULT
;=============
#WM_CHAR:
mov eax,wParam
cmp ax,VK_BACK ; this is for the backspace key
je #BACKSPACE
cmp ax,VK_0
jb #EXIT ; if null is returned, the char will not be passed to the edit box
cmp ax,VK_9
ja #EXIT
jmp #NUMBER
;---
#VK_DELETE:
#NUMBER:
invoke SendMessage,hWnd,EM_GETSEL,offset start,0 ; the caret position through text selection, we just need the starting position
cmp start,3
ja #DEFAULT ; if the caret is placed somewhere past the 4th charater, allow user input
jmp #EXIT
;---
#BACKSPACE:
invoke SendMessage,hWnd,EM_GETSEL,offset start,0
cmp start,4
ja #DEFAULT ; since you're deleting one character to the left, you need to factor that in for backspace
jmp #EXIT
EditProc endp
It's very cut, you hopefully get the gist of it. This example only allows the digits (0-9), the DEL and BACKSPACE keys through. You can expand to meet your needs.
Regards